具有 IErrorHandler 的 REST WCF 服务捕获 SerializationExceptions

发布于 2024-11-24 09:16:03 字数 1900 浏览 1 评论 0原文

我有一个带有自定义 IErrorHandler 的 REST WCF 服务,这样我就可以捕获服务中所有未捕获的异常并返回自定义错误消息、正确的 Http 状态代码 (500) 并记录错误。

问题是 IErrorHandler 将捕获并非源自我的代码的异常,因此,如果我使用无效的 JSON 数据向服务进行 POST,我将收到 SerializationException。如果不是我的 IErrorHandler,该异常将被转换为状态代码为 BadRequest 400 的 WebFaultException,我将像所有其他未捕获的异常一样处理它。

有没有办法处理这些情况,或者我应该在 IErrorHandler 中捕获 SerializationExceptions 并在那里设置 BadRequest ?还有哪些其他异常可能源自 WCF 堆栈而不来自我的代码?

更新:添加了我的 IErrorHandler.ProvideFault 实现

 public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
    {
        Guid loggingId = Guid.NewGuid();
        error.Data["ExceptionLoggingId"] = loggingId;

        if (error is SecurityTokenException)
        {
            fault = Message.CreateMessage(version, string.Empty, String.Format("{0}. The error identifier is {1}", error.Message, loggingId), new DataContractJsonSerializer(typeof(string)));
            fault.Properties.Add(WebBodyFormatMessageProperty.Name, new WebBodyFormatMessageProperty(WebContentFormat.Json));

            webOperationContextWrapper.SetOutgoingResponseStatusCode(HttpStatusCode.Unauthorized);
        }
        else
        {
            if (error is SerializationException)
            {
                // TODO: What if the SerializationException originates from within the service?
                // SerializationException due to malformed JSON
                return;
            }

            fault = Message.CreateMessage(version, string.Empty, String.Format("An unknown error has occurred. The error identifier is {0}", loggingId), new DataContractJsonSerializer(typeof(string)));
            fault.Properties.Add(WebBodyFormatMessageProperty.Name, new WebBodyFormatMessageProperty(WebContentFormat.Json));

            webOperationContextWrapper.SetOutgoingResponseStatusCode(HttpStatusCode.InternalServerError);
        }
}

I have a REST WCF service with a custom IErrorHandler, so that I can catch all uncaught exceptions in my service and return a custom error message, a proper Http status code (500) and log the error.

The problem is that the IErrorHandler will catch exceptions not originating from my code, so if I for example make a POST to the service with invalid JSON data, I will get a SerializationException. That exception would have been transformed into a WebFaultException with status code BadRequest 400, if it weren't for my IErrorHandler, where I will handle it just like all other uncaught exceptions.

Is there a way of dealing with these situations or should I just catch SerializationExceptions in my IErrorHandler and set BadRequest there? What other exceptions might orginate from the WCF stack without coming from my code?

Update: Added my implementation of IErrorHandler.ProvideFault

 public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
    {
        Guid loggingId = Guid.NewGuid();
        error.Data["ExceptionLoggingId"] = loggingId;

        if (error is SecurityTokenException)
        {
            fault = Message.CreateMessage(version, string.Empty, String.Format("{0}. The error identifier is {1}", error.Message, loggingId), new DataContractJsonSerializer(typeof(string)));
            fault.Properties.Add(WebBodyFormatMessageProperty.Name, new WebBodyFormatMessageProperty(WebContentFormat.Json));

            webOperationContextWrapper.SetOutgoingResponseStatusCode(HttpStatusCode.Unauthorized);
        }
        else
        {
            if (error is SerializationException)
            {
                // TODO: What if the SerializationException originates from within the service?
                // SerializationException due to malformed JSON
                return;
            }

            fault = Message.CreateMessage(version, string.Empty, String.Format("An unknown error has occurred. The error identifier is {0}", loggingId), new DataContractJsonSerializer(typeof(string)));
            fault.Properties.Add(WebBodyFormatMessageProperty.Name, new WebBodyFormatMessageProperty(WebContentFormat.Json));

            webOperationContextWrapper.SetOutgoingResponseStatusCode(HttpStatusCode.InternalServerError);
        }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

自找没趣 2024-12-01 09:16:03

我遇到了类似的问题。

我的解决方案是使用名称空间来确定异常的来源。

if (!error.StackTrace.TrimStart().StartsWith("at " + this.GetType().Namespace.Split('.')[0]))
    return;

这适用于我当前的项目。但根据您的项目,它可能不会...

I ran into a similar issue.

My Solution has been to use the namespace to determine the origin of the exception.

if (!error.StackTrace.TrimStart().StartsWith("at " + this.GetType().Namespace.Split('.')[0]))
    return;

This works in my current project. But depending on your project, it may not...

我的鱼塘能养鲲 2024-12-01 09:16:03

我认为 @RichardBlewett 说得对。您将需要创建一个自定义异常类并抛出它,在错误处理程序中检查该类型,然后让标准序列化异常正常流动。对我来说这似乎是最好的设计模式。

然后你会得到一个类型安全的异常,如果你删除或更改,错误处理程序代码将不会编译,或者如果你通过 VS 执行此操作,则会使用该类型进行重构。像这样测试命名空间可能不太可取(尽管非常聪明),因为它在编译时不直接绑定到任何类型。如果您更改名称空间,您将遇到难以追踪的问题。

I think @RichardBlewett has it right. You're going to want to create a custom exception class and throw that, check for that type in the error handler and then let the standard Serialization exception flow through normally. That seems like the best design pattern to me.

Then you get a type safe exception that if you remove or change, the error handler code won't compile or will get refactored with the type if you do it via VS. Testing the namespace like that would probably be less than advisable (though very clever), since it's not directly tied to any type at compile time. If you change namespaces around, you would run into a problem that's difficult to track down.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文