使用IErrorHandler的REST WCF服务捕获SerializationExceptions

时间:2011-07-18 08:37:34

标签: .net wcf rest ierrorhandler

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

问题是IErrorHandler会捕获不是源自我的代码的异常,所以如果我使用无效的JSON数据对服务进行POST,我将得到一个SerializationException。该异常将被转换为状态代码为BadRequest 400的WebFaultException,如果它不适用于我的IErrorHandler,我将处理它,就像所有其他未捕获的异常一样。

有没有办法处理这些情况,或者我应该只在我的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);
        }
}

2 个答案:

答案 0 :(得分:1)

我遇到了类似的问题。

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

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

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

答案 1 :(得分:0)

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

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