2010-09-13 3 views
2

Надеюсь, есть некоторые мастера WCF, которые могут обнаружить мою ошибку здесь.WCF IErrorHandler Расширение не возвращается указанный Fault

Я пытаюсь настроить глобальный обработчик ошибок с помощью поведения IErrorHandler на основе поведения в службе RESTful JSON WCF. Метод декорирован как таковой:

[OperationContract] 
[WebGet(UriTemplate = "screens/info", ResponseFormat = WebMessageFormat.Json)] 

Реализация IErrorHandler является:

public class ErrorHandler : IErrorHandler 
{ 
    public void ProvideFault(Exception error, 
          MessageVersion version, 
          ref Message fault) 
    { 
     var error = new JsonError 
         { 
          Message = error.Message, 
          FaultCode = -1, 
          StackTrace = error.StackTrace 
         }; 

     fault = Message.CreateMessage(version, 
        "", 
        ideaScreeningError, 
        new DataContractJsonSerializer(
         ideaScreeningError.GetType())); 

     // tell WCF to use JSON encoding rather than default XML 
     var wbf = new WebBodyFormatMessageProperty(WebContentFormat.Json); 
     fault.Properties.Add(WebBodyFormatMessageProperty.Name, wbf); 

     //Modify response 
     var rmp = new HttpResponseMessageProperty 
         { 
          StatusCode = HttpStatusCode.BadRequest, 
          StatusDescription = "Bad Request" 
         }; 

     fault.Properties.Add(HttpResponseMessageProperty.Name, rmp); 
    } 

    public bool HandleError(Exception error) 
    { 
     return true; 
    } 
} 

я могу проверить (с помощью контрольных точек), что расширение вызывается и выполняется должным образом. Когда я смотрю на результат вызова AJAX в браузере, я вижу, что WCF по-прежнему возвращает 500 Internal Server Error, а не данные Fault, которые я указал в обработчике ошибок.

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

Как заставить его остановиться !?

EDIT

Я добавление пользовательского поведения элемента:

public class ErrorBehaviorElement : BehaviorExtensionElement 
{ 
    protected override object CreateBehavior() 
    { 
     return new ErrorBehavior(); 
    } 

    public override Type BehaviorType 
    { 
     get { return typeof(ErrorBehavior); } 
    } 
} 

и поведение:

internal class ErrorBehavior : WebHttpBehavior 
{ 
    protected override void AddServerErrorHandlers(ServiceEndpoint endpoint, 
     EndpointDispatcher endpointDispatcher) 
    { 
     // clear default error handlers. 
     endpointDispatcher.ChannelDispatcher.ErrorHandlers.Clear(); 

     // add the Json error handler. 
     endpointDispatcher.ChannelDispatcher.ErrorHandlers.Add(
      new ErrorHandler()); 
    } 
} 
+0

Как добавить нового обработчика ошибок в службу? –

+0

@Ladislav - Via web.config с пользовательским элементом BehaviorExtensionElement –

+0

Да, я это понимаю, но меня интересовало ваше обычное поведение. –

ответ

5

Проблема здесь с WCF Rest Starter Kit (который я не понимал, был использован, так как я не начинал этот проект), а точнее WebServiceHost2. Я открыл ServiceHost в рефлектор и нашел этот прекрасный маленький кусочек кода в OnOpening():

if (endpoint.Behaviors.Find<WebHttpBehavior>() != null) 
{ 
    endpoint.Behaviors.Remove<WebHttpBehavior>(); 
    WebHttpBehavior2 item = new WebHttpBehavior2(); 
    // other code omitted 
    endpoint.Behaviors.Add(item); 
} 

Как вы можете видеть, независимо от того, какое поведение вы хотите добавлено в конечную точку, до тех пор, как он наследует от WebHttpBehavior Покой Start Компоненты набора будут захватывать ваш обработчик, удалять его и заменять его собственным.

Имейте в виду, что WebHttpBehavior2 также наследуется от WebHttBehavior, поэтому наследование с WebHttpBehavior2 в моем расширении ничего не помогло.

Первым шагом было создание нового WebSeriveHost, что производный от WebServiceHost2 и отменяют OnOpening() и повторно угон что Rest Starter Kit украла у меня:

if(endpoint.Behaviors.Find<WebHttpBehavior>() != null) 
{ 
    endpoint.Behaviors.Remove<WebHttpBehavior>(); 
    var item = ErrorBehavior(); 
    // other code 
    endpoint.Behaviors.Add(item); 
} 

А затем создать новый WebServiceHostFactory, которая возвращала мой обычай Тип WebServiceHost.

+0

Я ненавижу такие функции, которые просто меняют логику, даже не говоря вам. Слава богу, у нас есть рефлектор. –

0

Не забудьте установить ContentType ответа, а также :

rmp.Headers[HttpResponseHeader.ContentType] = "application/json"; 
0

Основываясь на комментариях, я попытался бы удалить общее webHttpBehavior. Вы определили свое собственное поведение, основанное на webHttp. В вашей конфигурации сервиса нет причин иметь два поведения webHttp. Кроме того, поведение webHttp добавляет собственный обработчик ошибок, который ведет себя точно так же, как вы описываете. Может быть, это не поможет, но вы можете попробовать.

+0

I дал мне шанс. Как ни странно, когда я удаляю webHttpBehavior, мое расширение больше не вызывается для обработки Exception. –

+0

Я понял, в чем проблема (наконец). Это было что-то совершенно неожиданное. Я разместил решение для вас –

Смежные вопросы