我的所有服務都具有enableWebScript行爲配置,只是因爲我認爲這是與現有客戶端應用程序集成最方便的行爲。這些應用程序包含一些相對複雜的表單。基本驗證在客戶端上執行,當服務接收到表單數據時,它們執行更全面的驗證。從支持ajax的WCF服務傳遞FaultException細節?
所以!當服務檢測到錯誤的數據合同時,它們將在ValidationErrorsSummary對象中編譯所有驗證錯誤,並拋出FaultException <ValidationErrorsSummary>。
我希望客戶端能夠檢索ValidationErrorsObject,但因爲我沒有啓用includeExceptionDetailInFaults,他們只是得到:
{"ExceptionDetail":null,"ExceptionType":null,"Message":"The server was unable to process the request due to an internal error. For more information about the error, either turn on IncludeExceptionDetailInFaults (either from ServiceBehaviorAttribute or from the <serviceDebug> configuration behavior) on the server in order to send the exception information back to the client, or turn on tracing as per the Microsoft .NET Framework SDK documentation and inspect the server trace logs.","StackTrace":null}
我已經試過:
1)通過實現IErrorHandler來創建自定義錯誤處理程序,但它似乎不與enableWebScript一起使用。代碼運行,但是響應堅持默認爲202接受而沒有客戶端收到響應主體。我已嘗試創建附加到服務本身的IServiceBehavior屬性,並通過將服務行爲配置爲web.config中的自定義配置元素。
public class ErrorWebHttpBehavior : WebHttpBehavior
{
protected override void AddServerErrorHandlers(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
// clear default error handlers.
endpointDispatcher.ChannelDispatcher.ErrorHandlers.Clear();
// add our own error handler.
endpointDispatcher.ChannelDispatcher.ErrorHandlers.Add(new ValidationErrorHandler());
}
}
public class ValidationErrorBehaviorAttribute : Attribute, IServiceBehavior
{
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
foreach (ChannelDispatcherBase channelDispatcher in serviceHostBase.ChannelDispatchers)
{
var dispatcher = channelDispatcher as ChannelDispatcher;
if (dispatcher != null)
dispatcher.ErrorHandlers.Add(new ValidationErrorHandler());
}
}
// ...
}
public class ValidationErrorHandler : IErrorHandler
{
public bool HandleError(Exception error)
{
return true;
}
public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
{
object details;
var summary = error as FaultException<ValidationErrorsSummary>;
if (error != null)
details = summary.Detail.Errors;
else
details = "The server was unable to process the request due to an internal error.";
// create a fault message containing our FaultContract object
fault = Message.CreateMessage(version, "", details, new DataContractJsonSerializer(details.GetType()));
// tell WCF to use JSON encoding rather than default XML
var wbf = new WebBodyFormatMessageProperty(WebContentFormat.Json);
fault.Properties.Add(WebBodyFormatMessageProperty.Name, wbf);
// return custom error code.
var rmp = new HttpResponseMessageProperty();
rmp.StatusCode = System.Net.HttpStatusCode.BadRequest;
rmp.StatusDescription = "Bad request";
fault.Properties.Add(HttpResponseMessageProperty.Name, rmp);
}
}
// ...
var summary = new ValidationErrorsSummary { Errors = validator.Errors };
throw new WebFaultException<ValidationErrorsSummary>(summary, System.Net.HttpStatusCode.BadRequest);
2)截取請求本身,並使用的HttpContext到回覆於到響應流。這不起作用的反應是由於某種原因,加蓋到10個字符(即使我的的Content-Length設置爲JSON字符串的長度。
那麼,應該怎麼辦?任何想法?我不想要傳達的任意異常信息,但我真的想我的驗證摘要到達客戶。
我已經簽出的源代碼WebScriptEnablingBehavior,發現這個JsonFaultBodyWriter內班級:
if (includeExceptionDetailInFaults)
{
faultDetail.Message = fault.Reason.ToString();
if (fault.HasDetail)
{
try
{
ExceptionDetail originalFaultDetail = fault.GetDetail<ExceptionDetail>();
faultDetail.StackTrace = originalFaultDetail.StackTrace;
faultDetail.ExceptionType = originalFaultDetail.Type;
faultDetail.ExceptionDetail = originalFaultDetail;
}
// ...
}
}
else
{
faultDetail.Message = System.ServiceModel.SR.GetString(System.ServiceModel.SR.SFxInternalServerError);
}
我可以通過查看源代碼做兩個假設:
對於ExceptionDetails來填充,你必須確保你拋出一個的FaultException <ExceptionDetail>例外,
或至少,在我的情況下,確保ValidationErrorsSummary繼承該類。這不起作用,因爲GetDetail使用序列化程序檢索細節,並且由於自定義派生類不是ExceptionDetail類的已知類型,因此序列化將失敗。所以你必須堅持基類。如果不啓用includeExceptionDetailInFaults,就無法接收有關故障的信息。我的意思是,你甚至沒有控制錯誤信息。
這真的很糟糕。 :(