2016-01-21 83 views
0

我的所有服务都具有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,就无法接收有关故障的信息。我的意思是,你甚至没有控制错误信息。

这真的很糟糕。 :(

回答

0

我已经决定放弃这个想法由于WebScriptEnablingBehavior类的实现方式。我会“攻击”的事实,这是一个Web服务,并传达验证错误的HTTP标头X-Validation-Errors