Бросать универсальный FaultException - PullRequest
4 голосов
/ 15 марта 2009

У меня есть служба WCF, которая, если что-то идет не так, генерирует общее исключение FaultException. Я не знаю почему, иногда клиенты будут ловить неуниверсальное исключение FaultException вместо универсального исключения.

Кто-нибудь знает, в чем проблема?

Ответы [ 7 ]

18 голосов
/ 15 марта 2009

Ваша служба должна обработать все исключения и включить их в FaultException , где T - это контракт на данные, который вы написали. Поэтому первым шагом является определение пользовательского контракта данных, который будет содержать информацию об исключении:

[DataContract]
public class CustomFault
{
    public string Message { get; set; }
}

Затем вы указываете своему контракту на обслуживание, что его методы потенциально могут вызвать FaultException . Это позволяет службе предоставлять класс CustomFault в wsdl, чтобы клиенты могли генерировать прокси-класс:

[ServiceContract]
public interface IMyServiceContract
{
    [FaultContract(typeof(CustomFault))]
    void MyMethod(string someArgument);
}

Следующим шагом является реализация этого интерфейса:

public class MyService : IMyServiceContract
{
    public void MyMethod(string someArgument)
    {
        // Do something here that could throw exceptions but don't catch yet
    }
}

Для обработки исключений вы можете реализовать IErrorHandler , который будет использоваться всякий раз, когда один из ваших методов обслуживания выдает исключение. Цель этого обработчика ошибок - заключить исключение в FaultException :

public class MyErrorHandler : IErrorHandler
{
    public bool HandleError(Exception error)
    {
        return true;
    }

    public void ProvideFault(Exception error, MessageVersion version, ref Message msg)
    {
        var customFault = new CustomFault()
        {
            Message = error.Message,
        };
        var fe = new FaultException<CustomFault>(customFault);
        MessageFault fault = fe.CreateMessageFault();
        string ns = "http://somenamespace/whatever";
        msg = Message.CreateMessage(version, fault, ns);
    }
}

Как только вы зарегистрируете свой обработчик ошибок, на стороне клиента вы всегда получите FaultException .

5 голосов
/ 07 января 2011

Если ваш клиент не имеет доступа к самому типу исключения ( на FaultException ), то генерируется неуниверсальная версия FaultException. Я потратил часы, пытаясь понять это, и в конце концов осознал это, когда обнаружил this на форумах msdn. Было бы замечательно, если бы было какое-то указание на то, что исключение было изменено до его выброса из службы, но это не так.

2 голосов
/ 15 марта 2009

Другая возможность состоит в том, что ваш TDetail не сериализуется должным образом. Это может иметь место, если, например, TDetail происходит от Exception, и у вас есть внутреннее исключение, которое не сериализуемо.

2 голосов
/ 15 марта 2009

Неуниверсальный FaultException генерируется, когда служба генерирует другое исключение, которое не было перехвачено. Вам нужно выяснить, что такое исключение, и исправить его, если это ошибка, или решить, что это то, что вы хотите показать своим клиентам, затем обернуть его в общий FaultException и добавить FaultContract соответствующим образом.

1 голос
/ 30 марта 2012

Я видел ту же проблему, и ссылка, которую разместил Дрю, дала мне ответ.

Для меня было решено, что мой интерфейс службы имел другое пространство имен, чем моя ошибка службы.

т. Е. Договор на обслуживание имел:

[ServiceContract(Namespace = "http://dummydomain.com/service/searchservice")]
    public interface ISearchService
    ....

и ошибка обслуживания:

[DataContract(Namespace = "http://dummydomain.com/service/searchservicefault")]
public class MySearchServiceFault
...

очевидно, когда пространства имен различаются, клиент не знает, что с ним делать, и возвращается к не универсальному FaultContract ... Я думаю, что это в некоторой степени зависит от клиента, так как я видел, как работает приведенный выше код, и возвращает универсальный FaultContract ...

Но когда я изменил пространство имен на одно и то же, это, похоже, заставило код работать все время в моем тестировании.

1 голос
/ 31 марта 2011

Это произойдет, если вы не объявили свой тип сведений об ошибке с помощью FaultContractAttribute.

Вот как должен выглядеть ваш контракт на обслуживание:

[ServiceContract]
public interface IMyServiceContract
{
    //...
    [OperationContract]
    [FaultContract(typeof(MyFaultDetail))]
    [FaultContract(typeof(OtherFaultDetail))] 
    GetDetailsResp GetDetails(GetDetailsReq req);
    //...
}
0 голосов
/ 16 декабря 2018

У меня была похожая проблема, и это произошло, когда я обновил некоторые пакеты NuGet, использовал общий стандартный класс .NET и т. Д. (Я не знаю точно, что вызвало это, за два месяца произошло много изменений, но эти были среди изменений). Это оказалось проблемой, когда Action было установлено в строку «FAULT» ранее, и она работала нормально на стороне клиента с атрибутами FaultContract по умолчанию. Но после этих изменений (конец 2018 года) строка «НЕИСПРАВНОСТЬ» как действие означала, что она больше не соответствует классам неисправностей, и вместо этого я получил общее исключение FaultException. Изменения, которые исправили все это (без изменений на стороне клиента), заключались в том, чтобы установить для действия значение «null» при возникновении исключения FaultException вместо «FAULT» . Я решил опубликовать это исправление здесь в качестве ответа, если кто-то еще столкнется с этим.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...