繁体   English   中英

从启用了Ajax的WCF服务传达FaultException详细信息?

[英]Convey FaultException details from an ajax-enabled WCF service?

我所有的服务都具有enableWebScript行为配置,这仅仅是因为我认为这是与现有客户端应用程序集成的最方便的行为。 应用程序由一些相对复杂的形式组成。 基本验证是在客户端上执行的,当服务接收到表单数据时,它们将执行更全面的验证。

所以! 当服务检测到错误的数据约定时,它们将在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)拦截请求本身,并使用HttpContextResponse.Write到响应流。 这不起作用,因为出于某种原因,响应被限制为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,就无法接收有关故障的信息。 我的意思是,您甚至无法控制错误消息。

这真的很糟糕。 :(

由于WebScriptEnablingBehavior类的实现方式,我决定放弃这个想法。 我将“利用”它是一个Web服务这一事实,并将验证错误作为HTTP标头而不是X-Validation-Errors传递。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM