0
的open311協議需要用於以下列格式端點支持:WCF自定義錯誤處理程序有條件地返回XML或JSON?
- 域/ requests.xml
- 域/ requests.json
的第一端點接受XML請求,所述第二請求JSON 。
協議進一步指定錯誤應以請求格式(xml或json)返回。
在實現ServiceBehaviorErrorHandler時,我發現無法確定ProvideFault方法中的請求格式(xml或json)。所有示例或者返回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
}