【问题标题】:WCF IErrorHandler Extension not returning specified FaultWCF IErrorHandler Extension 未返回指定的故障
【发布时间】:2010-09-13 17:56:13
【问题描述】:

希望有一些 WCF 向导可以在这里发现我的错误。

我正在尝试通过基于 IErrorHandler 的 behaviorExtension 在 RESTful JSON WCF 服务上设置全局错误处理程序。方法是这样装饰的:

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

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;
    }
}

我可以验证(通过断点)扩展正在被调用并且正在正确执行。当我在浏览器中查看 AJAX 调用的结果时,我可以看到 WCF 仍然返回 500 Internal Server Error 而不是我在错误处理程序中指定的故障详细信息。

如果我更改 WCF 方法中抛出的异常类型,它们会反映在浏览器的结果中,因此我可以推测 WCF 正在做一些事情来处理异常并在内部返回一些内容。

如何让它停止!?

编辑

我正在添加自定义行为元素:

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

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

和行为:

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());
    }  
}

【问题讨论】:

  • 如何将新的错误处理程序添加到服务中?
  • @Ladislav - 通过带有自定义 BehaviorExtensionElement 的 web.config
  • 是的,我明白这一点,但我对您的自定义行为感兴趣。
  • @Ladislav - 我刚刚添加了所涉及的其余代码。
  • 您是在普通的 XmlHttpRequest / jQuery 中还是在 ASP.NET AJAX / ScriptManager 中使用服务?

标签: c# wcf json web-config


【解决方案1】:

这里的问题在于 WCF Rest Starter Kit(我没有意识到它正在使用,因为我没有启动这个项目),更具体地说是WebServiceHost2。我在 Reflector 中打开了 ServiceHost,在OnOpening() 中发现了这段可爱的小代码:

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

如您所见,无论您想向端点添加什么行为,只要它继承自 WebHttpBehavior,Rest Start Kit 组件就会劫持您的处理程序,将其删除,并用自己的处理程序替换。

请记住,WebHttpBehavior2 也继承自 WebHttBehavior,因此在我的扩展程序中从 WebHttpBehavior2 继承对解决问题没有任何帮助。

第一步是创建一个派生自WebServiceHost2 并覆盖OnOpening() 的新WebSeriveHost,并重新劫持Rest Starter Kit 从我那里偷来的东西:

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

然后创建一个返回我的自定义 WebServiceHost 类型的新 WebServiceHostFactory。

【讨论】:

  • 不错。我讨厌这些简单地改变逻辑而不告诉你的功能。感谢上帝,我们有 Reflector。
【解决方案2】:

不要忘记设置响应的 ContentType:

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

【讨论】:

    【解决方案3】:

    基于 cmets,我会尝试删除常见的 webHttpBehavior。您已经定义了从 webHttp 派生的自己的行为。没有理由在您的服务配置中有两个 webHttp 行为。此外,webHttp 行为添加了自己的错误处理程序,其行为与您描述的完全一样。或许没用,但你可以试试看。

    【讨论】:

    • 我试了一下。奇怪的是,当我删除 webHttpBehavior 时,不再调用我的扩展来处理异常。
    • 我(终于)弄清楚了问题所在。这完全出乎意料。我发布了解决方案供您查看。
    猜你喜欢
    • 2013-06-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-29
    • 2010-12-06
    • 1970-01-01
    相关资源
    最近更新 更多