WCF - веб-служба, работающая в IIS, но через фабрику не поддерживает исходное исключение - PullRequest
2 голосов
/ 04 января 2012

Веб-служба, работающая в IIS, но через фабрику не поддерживает исходное выброшенное исключение.

Например:

Мой веб-сервис был помечен как FaultContractAttribute следующим образом:

public interface IMyService
{
    [FaultContract(typeof(MyCustomException))]
    [OperationContract]
    bool IsAuthorized();
}

В моей реализации веб-службы выдается специальное исключение, подобное следующему:

public class MyService : IMyService
{
    public bool IsAuthorized()
    {
        throw new FaultException<MyCustomException>(fault, fr);
    }
}

Тогда:

  1. Если мой WCF- НЕ использует какую-либо фабрику - похоже на <%@ ServiceHost Language="C#" Debug="true" Service="MyService" %>, тогда на стороне клиента я МОГУ выбрать исходное исключение (MyCustomException)

  2. Если мой WCF - ИСПОЛЬЗУЯ некоторую фабрику - похож на<%@ ServiceHost Language="C#" Debug="true" Service="MyService" Factory="MyFactory" %>, затем на стороне клиента я не могу подобрать исходное исключение (MyCustomException), но только исключение SOAP (FaultException) с бесполезной общей трассировкой и сообщением

Примечание:

Фабрика WCF MyFactory реализована с помощью своего SERVICE HOST, содержащего SERVICE BEHAVIOR, инициированный из IErrorHandler

В этом поведении службы метод ProvideFault ничего не делает (я не знал, как сохранитьтаким образом, исходное исключение)

Итак, я прошу ответы от ожидаемого: как сохранить исходное исключение (MyCustomException) при использовании некоторой фабрики WCF?Спасибо.

1 Ответ

1 голос
/ 06 апреля 2012

В моем недавнем проекте (службы WCF REST) ​​я использую WebServiceHostFactory , и я все еще смог достичь этого с помощью IErrorHandler .Ниже приведен пример

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

[Serializable]
public class ExceptionInfo
{
    public string ExceptionType { get; set; }
    public string ExceptionMessage { get; set; }
    public string StackTrace { get; set; }
}

И реализовать собственный обработчик ошибок

[DataContract]
public class MyCustomServiceErrorHandler : IErrorHandler
{
    #region IErrorHandler Members

    /// <summary>
    /// This method will execute whenever an exception occurs in WCF method execution
    /// </summary>
    public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
    {
        var exceptionInfo = new ExceptionInfo();

        if (error is MyCustomException)
            exceptionInfo.ExceptionType = error.Type.ToString();;
        else
            exceptionInfo.Type = "Unhandled Exception";

        exceptionInfo.ExceptionMessage = error.Message;            
        exceptionInfo.StackTrace = error.StackTrace;

        var faultException = new FaultException<ExceptionInfo>(exceptionInfo);

        object detail = faultException.GetType().GetProperty("Detail").GetGetMethod().Invoke(faultException, null);

        fault = Message.CreateMessage(version, "", detail, new DataContractSerializer(detail.GetType()));

        var webBodyFormatMessageProp = new WebBodyFormatMessageProperty(WebContentFormat.Xml);

        fault.Properties.Add(WebBodyFormatMessageProperty.Name, webBodyFormatMessageProp);

        var httpResponseMessageProp = new HttpResponseMessageProperty();

        httpResponseMessageProp.Headers[HttpResponseHeader.ContentType] = "application/xml";
        httpResponseMessageProp.StatusCode = HttpStatusCode.BadRequest;
        httpResponseMessageProp.StatusDescription = exceptionInfo.ExceptionMessage;

        fault.Properties.Add(HttpResponseMessageProperty.Name, httpResponseMessageProp);

    }

    /// <summary>
    /// Performs error related behavior
    /// </summary>
    /// <param name="error">Exception raised by the program</param>
    /// <returns></returns>
    public bool HandleError(Exception error)
    {
        // Returning true indicates that an action(behavior) has been taken (in ProvideFault method) on the exception thrown.
        return true;
    }

Теперь вы можете украсить свои службы с помощью вышеуказанного обработчика.

[ServiceContract]    
[ServiceErrorBehavior(typeof (MyCustomServiceErrorHandler))]
public class LoginService : ServiceBase
{}

На стороне клиента вы можете проверить, является ли HttpStatusCode ответа! = Ok, и десериализовать ответ для типа ExceptionInfo и отобразить его в окне сообщенияили справиться с требованием.

Надеюсь, это поможет.

...