Пользовательский обработчик ошибок WCF для условного возврата XML или JSON?
Протокол open311 требует поддержки конечных точек в следующем формате:
- домен /requests.xml
- домен /requests.json
Первая конечная точка принимает запросы XML, вторая - запросы JSON.
Протокол также указывает, что ошибки должны быть возвращены в формате запроса (xml или json).
При реализации ServiceBehaviorErrorHandler я обнаружил, что невозможно определить формат запроса (xml или json) в методе ProvideFault. Все примеры либо возвращают json или xml.
Как определить формат запроса, чтобы я мог вернуть сообщение об ошибке в том же формате? Моя реализация:
/// <summary>
/// From http://www.codeproject.com/Articles/43621/Extending-WCF-Part-I
/// </summary>
public class ExtendedServiceErrorHandler : IErrorHandler, IServiceBehavior
{
#region IErrorHandler Members
bool IErrorHandler.HandleError( Exception error )
{
return ( error is Open311Exception );
}
/*
* TODO: HTTP error codes are required, but the code in the response body shouldn't necessarily match the HTTP error code,
* so that more specific and unique error code identifiers can be used.
* The HTTP error codes should always be 404 for resources that don't exist,
* 403 for errors because of wrong or missing api_key and basically
* 400 for any other error where the request can not be fulfilled as expected.
* Multiple errors codes and descriptions can be returned in the body (the response is an array).
*/
void IErrorHandler.ProvideFault( Exception error, MessageVersion version, ref Message fault )
{
var ajaxErrors = new AjaxErrors();
var open311Error = error as Open311Exception;
if( null != open311Error )
{
ajaxErrors.Add( new AjaxError()
{
Code = open311Error.Code,
Message = open311Error.Message
} );
}
else
{
ajaxErrors.Add( new AjaxError()
{
Code = 400,
Message = error.Message
} );
}
var contentType = "application/json"; // TODO: how do we know?
// WebOperationContext.Current.IncomingRequest.ContentType doesn't work
WebContentFormat webContentFormat;
switch( contentType )
{
case "application/json":
fault = Message.CreateMessage( version, string.Empty, ajaxErrors, new DataContractJsonSerializer( ajaxErrors.GetType() ) );
webContentFormat = WebContentFormat.Json;
break;
case "application/xml":
fault = Message.CreateMessage( version, string.Empty, ajaxErrors, new DataContractSerializer( ajaxErrors.GetType() ) );
webContentFormat = WebContentFormat.Xml;
break;
default:
fault = Message.CreateMessage( version, string.Empty, ajaxErrors, new DataContractSerializer( ajaxErrors.GetType() ) );
webContentFormat = WebContentFormat.Raw;
break;
}
var wbf = new WebBodyFormatMessageProperty( webContentFormat );
fault.Properties.Add( WebBodyFormatMessageProperty.Name, wbf );
WebOperationContext.Current.OutgoingResponse.ContentType = contentType;
WebOperationContext.Current.OutgoingResponse.StatusCode = HttpStatusCode.OK; // HttpStatusCode.BadRequest;
}
#endregion
#region IServiceBehavior Members
void IServiceBehavior.AddBindingParameters( ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters )
{
// nothing to do?
}
void IServiceBehavior.ApplyDispatchBehavior( ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase )
{
var errorHandler = new ExtendedServiceErrorHandler();
foreach( ChannelDispatcher channelDispatcher in serviceHostBase.ChannelDispatchers )
{
channelDispatcher.ErrorHandlers.Add( errorHandler );
}
}
void IServiceBehavior.Validate( ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase )
{
// nothing to do?
}
#endregion
}
1 ответ
Я верю в то, что вы ищете: http://msdn.microsoft.com/en-us/library/vstudio/ee513227(v=vs.100).aspx
Обработка ошибок веб-HTTP Windows Communication Foundation (WCF) позволяет возвращать ошибки из веб-служб WCF HTTP, которые задают код состояния HTTP, и возвращать сведения об ошибках, используя тот же формат, что и операция (например, XML или JSON).