WCF IErrorHandler Расширение не возвращает указанный сбой
Надеюсь, что есть несколько волшебников WCF, которые могут заметить мою ошибку здесь.
Я пытаюсь настроить глобальный обработчик ошибок с помощью поведения Extension на основе 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, а не сведения о сбое, которые я указал в обработчике ошибок.
Если я изменяю типы исключений, создаваемые в методе WCF, они отражаются в результате в браузере, поэтому я могу предположить, что WCF что-то делает для обработки исключения и возвращает что-то внутренне.
Как мне это остановить!?
РЕДАКТИРОВАТЬ
Я добавляю пользовательский элемент поведения:
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());
}
}
3 ответа
Проблема здесь заключается в WCF Rest Starter Kit (который я не знал, использовался, так как я не начинал этот проект), более конкретно WebServiceHost2
, Я открыл ServiceHost в Reflector и нашел этот прекрасный маленький кусочек кода в OnOpening()
:
if (endpoint.Behaviors.Find<WebHttpBehavior>() != null)
{
endpoint.Behaviors.Remove<WebHttpBehavior>();
WebHttpBehavior2 item = new WebHttpBehavior2();
// other code omitted
endpoint.Behaviors.Add(item);
}
Как вы можете видеть, независимо от того, какое поведение вы хотите добавить в конечную точку, поскольку она наследует от WebHttpBehavior, компоненты Rest Start Kit будут захватывать ваш обработчик, удалять его и заменять его собственным.
Имейте в виду, что WebHttpBehavior2 также наследуется от WebHttBehavior, поэтому наследование от WebHttpBehavior2 в моем расширении не помогло.
Первым шагом было создание нового WebSeriveHost, который получен из WebServiceHost2
и перебор OnOpening()
и перехитрить то, что у меня украл у меня Стартовый набор для отдыха:
if(endpoint.Behaviors.Find<WebHttpBehavior>() != null)
{
endpoint.Behaviors.Remove<WebHttpBehavior>();
var item = ErrorBehavior();
// other code
endpoint.Behaviors.Add(item);
}
А затем создайте новый WebServiceHostFactory, который вернул мой пользовательский тип WebServiceHost.
Не забудьте также указать ContentType ответа:
rmp.Headers[HttpResponseHeader.ContentType] = "application/json";
На основании комментариев я бы попытался удалить общий webHttpBehavior. Вы определили свое собственное поведение, полученное из webHttp. Нет никаких причин иметь два поведения webHttp в конфигурации вашей службы. Более того, поведение webHttp добавляет свой собственный обработчик ошибок, который ведет себя именно так, как вы описали. Может быть, это не поможет, но вы можете попробовать.