具有 IErrorHandler 的 REST WCF 服务捕获 SerializationExceptions
我有一个带有自定义 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我遇到了类似的问题。
我的解决方案是使用名称空间来确定异常的来源。
这适用于我当前的项目。但根据您的项目,它可能不会...
I ran into a similar issue.
My Solution has been to use the namespace to determine the origin of the exception.
This works in my current project. But depending on your project, it may not...
我认为 @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.