open311 프로토콜은 다음과 같은 형식의 엔드 포인트에 대한 지원이 필요합니다조건부로 xml 또는 json을 반환하는 WCF 사용자 지정 오류 처리기?
- 도메인/requests.xml을
- 첫 번째 엔드 포인트는 XML 요청, 두 번째 JSON 요청을 수락
도메인/requests.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
}