簡體   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