简体   繁体   English

WCF IErrorHandler扩展未返回指定的错误

[英]WCF IErrorHandler Extension not returning specified Fault

Hopefully there are some WCF wizards out there that can spot my mistake here. 希望那里有一些WCF向导可以在这里发现我的错误。

I am trying to set up a global error handler via an IErrorHandler based behaviorExtension on a RESTful JSON WCF Service. 我试图通过基于RESTful JSON WCF服务的基于IErrorHandler的behaviorExtension设置全局错误处理程序。 The method is decorated as such: 该方法的修饰如下:

[OperationContract]
[WebGet(UriTemplate = "screens/info", ResponseFormat = WebMessageFormat.Json)]

The IErrorHandler implementation is: IErrorHandler实现是:

public class ErrorHandler : IErrorHandler
{
    public void ProvideFault(Exception error, 
                             MessageVersion version, 
                             ref Message fault)
    {
        var error = new JsonError 
                        { 
                            Message = error.Message, 
                            FaultCode = -1, 
                            StackTrace = error.StackTrace
                        };

        fault = Message.CreateMessage(version, 
                    "", 
                    ideaScreeningError, 
                    new DataContractJsonSerializer(
                        ideaScreeningError.GetType()));

        // tell WCF to use JSON encoding rather than default XML
        var wbf = new WebBodyFormatMessageProperty(WebContentFormat.Json);
        fault.Properties.Add(WebBodyFormatMessageProperty.Name, wbf);

        //Modify response
        var rmp = new HttpResponseMessageProperty 
                      { 
                          StatusCode = HttpStatusCode.BadRequest, 
                          StatusDescription = "Bad Request"
                      };

        fault.Properties.Add(HttpResponseMessageProperty.Name, rmp);
    }

    public bool HandleError(Exception error)
    {
        return true;
    }
}

I can verify (via breakpoints) that the extension is being called and is executing properly. 我可以验证(通过断点)该扩展名正在被调用并且正在正确执行。 When I look at the result of the AJAX call in the browser, I can see that WCF is still returning a 500 Internal Server Error rather than the Fault details that I've specified in the error handler. 当我在浏览器中查看AJAX调用的结果时,可以看到WCF仍返回500 Internal Server Error,而不是我在错误处理程序中指定的Fault详细信息。

If I change Exception types being thrown in the WCF method, those are reflected in the result in the browser so I can surmise that WCF is doing something to handle the Exception and return something internally. 如果我更改了WCF方法中引发的Exception类型,则这些类型将反映在浏览器的结果中,因此我可以推测WCF正在做某些事情来处理Exception并在内部返回某些内容。

How do I make it stop!? 我如何使其停止!?

EDIT 编辑

I'm adding the custom Behavior Element: 我要添加自定义行为元素:

public class ErrorBehaviorElement : BehaviorExtensionElement
{
    protected override object CreateBehavior()
    {
        return new ErrorBehavior();
    }

    public override Type BehaviorType
    {
        get { return typeof(ErrorBehavior); }
    }
}

And Behavior: 和行为:

internal class ErrorBehavior : WebHttpBehavior
{
    protected override void AddServerErrorHandlers(ServiceEndpoint endpoint,
        EndpointDispatcher endpointDispatcher)
    {
        // clear default error handlers.  
        endpointDispatcher.ChannelDispatcher.ErrorHandlers.Clear();

        // add the Json error handler.  
        endpointDispatcher.ChannelDispatcher.ErrorHandlers.Add(
            new ErrorHandler());
    }  
}

The issue here lies with the WCF Rest Starter Kit (which I didn't realize was in use since I didn't start this project), more specifically WebServiceHost2 . 这里的问题在于WCF Rest Starter Kit(因为我没有启动该项目,所以没有意识到它在使用中),更具体地说是WebServiceHost2 I opened the ServiceHost in Reflector and found this lovely little piece of code in OnOpening() : 我在Reflector中打开了ServiceHost,并在OnOpening()发现了这段可爱的小代码:

if (endpoint.Behaviors.Find<WebHttpBehavior>() != null)
{
    endpoint.Behaviors.Remove<WebHttpBehavior>();
    WebHttpBehavior2 item = new WebHttpBehavior2();
    // other code omitted
    endpoint.Behaviors.Add(item);
}

As you can see, no matter what behavior you want added to the endpoint, as long as it inherits from WebHttpBehavior the Rest Start Kit components will hijack your handler, remove it, and replace it with its own. 如您所见,无论您要添加到端点的任何行为,只要它继承自WebHttpBehavior,Rest Start Kit组件都将劫持您的处理程序,将其删除,并将其替换为自己的处理程序。

Keep in mind that WebHttpBehavior2 also inherits from WebHttBehavior so inheriting from WebHttpBehavior2 in my extension did nothing to help the matter. 请记住,WebHttpBehavior2也继承自WebHttBehavior,因此在我的扩展程序中继承自WebHttpBehavior2并没有帮助。

The first step was to create a new WebSeriveHost that derived from WebServiceHost2 and overrode OnOpening() and re-hijack what the Rest Starter Kit stole from me: 第一步是创建一个从WebServiceHost2派生的新WebSeriveHost,并覆盖OnOpening()并重新劫持Rest Starter Kit从我那里偷来的东西:

if(endpoint.Behaviors.Find<WebHttpBehavior>() != null)
{
    endpoint.Behaviors.Remove<WebHttpBehavior>();
    var item = ErrorBehavior();
    // other code
    endpoint.Behaviors.Add(item);
}

And then create a new WebServiceHostFactory that returned my custom WebServiceHost type. 然后创建一个新的WebServiceHostFactory,它返回了我的自定义WebServiceHost类型。

不要忘记也设置响应的ContentType:

rmp.Headers[HttpResponseHeader.ContentType] = "application/json";

Based on comments I would try to remove common webHttpBehavior. 根据评论,我将尝试删除常见的webHttpBehavior。 You have defined your own behavior derived from webHttp. 您已经定义了从webHttp派生的自己的行为。 There is no reason to have two webHttp behaviors in your service configuration. 您的服务配置中没有理由出现两种webHttp行为。 Moreover webHttp behavior adds its own error handler which behaves exactly as you describe. 此外,webHttp行为还添加了自己的错误处理程序,其行为与您描述的完全相同。 Maybe it will not help but you can give it a try. 也许没有帮助,但是您可以尝试一下。

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

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