【问题标题】:Capture exception during request deserialization in WebAPI C#在 WebAPI C# 中的请求反序列化期间捕获异常
【发布时间】:2015-05-04 08:15:40
【问题描述】:

我正在使用 WebAPI v2.2,并且我正在让 WebAPI 使用 [FromBody] 属性将 JSON 反序列化到一个对象上。反序列化的目标类在内部方法上有一个 [OnDeserialized] 属性,如下所示:

[OnDeserialized]
internal void OnDeserialisedMethod(StreamingContext context) {
    // my method code
}

我知道这个方法中的代码有问题,我已经通过它找到了它。对我来说,问题是我一点也不例外。发生的情况是这个方法被跳出并且异常似乎被忽略了。我的控制器动作被调用并且我的目标对象没有被正确填充,因为这个序列化方法没有被正确执行。

我的问题是;如何在 WebAPI 中捕获反序列化期间发生的异常?

【问题讨论】:

  • 我已按照该网页上的建议进行操作,但仍然没有发现异常?从 ExceptionHandler 类派生并注册到config.Services.Replace(typeof(IExceptionHandler), new Exceptions.MyExceptionHandler());
  • 他们确实捕获了异常,但不是我想要的异常。它捕获了我的目标类没有正确填充的异常,它仍然没有看到 OnDeserialized 方法的任何异常。我需要在它进入控制器操作方法之前捕获错误,这似乎是这里的一个问题,它们似乎只是被忽略了。
  • 对不起,这是我的错。它是用于响应序列化而不是用于请求反序列化。
  • 没问题,我已将标题更新为声明请求反序列化,因为我认为这样会更清楚。

标签: c# json asp.net-web-api deserialization


【解决方案1】:

我编写了一个过滤器(如各种 cmets 中所建议的那样),它检查 ModelState 并在确实发生序列化错误时抛出异常。但请注意,这可能不仅仅包含序列化异常 - 可以通过在 Select 语句中指定具体的异常类型来调整。

public class ValidModelsOnlyFilter : ActionFilterAttribute
{
    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        if (actionContext.ModelState.IsValid)
        {
            base.OnActionExecuting(actionContext);
        }
        else
        {
            var exceptions = new List<Exception>();

            foreach (var state in actionContext.ModelState)
            {
                if (state.Value.Errors.Count != 0)
                {
                    exceptions.AddRange(state.Value.Errors.Select(error => error.Exception));
                }
            }

            if (exceptions.Count > 0)
                throw new AggregateException(exceptions);
        }
    }
}

我建议将此过滤器绑定到全局范围。我真的无法理解为什么可以忽略反序列化异常。

【讨论】:

  • 自动投票支持提出全局解决方案,而不是对单个方法进行内联检查。
【解决方案2】:

我遇到了完全相同的问题,并为您的问题添加了书签,希望有人能提供解决方案。我认为使用 ModelState 意味着在 JSON 模型中重写一些验证,但它确实有效,实际上它很简单而且做得很好。我不必修改模型,只需修改控制器即可。

来自我的一个控制器的代码,StdResponse 是用于在需要时为响应提供详细信息的类(例如,在这种情况下):

[HttpPost]
public StdResponse Test([FromBody]StdRequest request)
{
    if (ModelState.IsValid)
    {
        //Work on the data from the request...
    }
    else
    {
        //Retrieve the exceptions raised during deserialization
        var errors = ModelState.SelectMany(v => v.Value.Errors.Select(e => e.Exception));

        List<String> messages = new List<string>();

        foreach (Exception e in errors)
        {
            messages.Add(e.GetType().ToString() + ": " + e.Message);
        }

        return new StdResponse(exchangeVersion, "null", ExecutionResponse.WithError("StdRequest invalid", messages));
    }
}

【讨论】:

    【解决方案3】:

    您可以在控制器中检查 ModelState.IsValid。 如果“OnDeserialisedMethod”抛出异常(或任何其他模型验证失败),它将为 false,如果一切成功,则为 true。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-09-22
      • 2018-12-02
      • 2013-02-07
      • 1970-01-01
      • 1970-01-01
      • 2014-01-20
      • 1970-01-01
      相关资源
      最近更新 更多