处理将操作参数绑定到不正确类型的路由值时出现的错误

Con*_*ell 5 c# asp.net-mvc-4 asp.net-web-api

我在处理 ASP.NET WebAPI 中的所有类型的错误时遇到了麻烦。

我已经使用ExceptionFilter成功处理了操作方法中引发的异常,并成功处理了无效路由、无效控制器或操作名称的 404 错误。但是,我正在努力处理控制器和操作都找到的错误,但模型绑定的参数类型不正确。

这是我的操作,它被路由到/api/users/{id}.

[HttpGet]
public virtual TPoco Get(long id)
{
    ...
}
Run Code Online (Sandbox Code Playgroud)

如果我请求 URL /api/users/notinteger,我会收到一个400 Bad Request在代码之外处理的错误:

{
Message: "The request is invalid.",
MessageDetail: "The parameters dictionary contains a null entry for parameter 'id' of non-nullable type 'System.Int64' for method '___ Get(Int64)' in '___'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter."
}
Run Code Online (Sandbox Code Playgroud)

我如何拦截此错误并用我自己的错误消息进行响应?最好不在控制器本身,因为我想以相同的方式处理多个控制器。

我已经尝试根据这个问题global.asax.cs使用's事件,但在这种情况下似乎没有被调用。Application_Error

Con*_*ell 1

看来这些错误已作为模型绑定错误添加到 ModelState 中。操作选择器选择正确的操作,并且操作调用器调用它而不会抛出任何错误。

我想出的解决方法是创建一个操作调用程序来检查ModelState错误。如果找到任何异常,它会将第一个传递给 myExceptionFilter和使用的异常处理方法ErrorController

internal class ThrowModelStateErrorsActionInvoker : ApiControllerActionInvoker
{
    public override Task<HttpResponseMessage> InvokeActionAsync(HttpActionContext actionContext, CancellationToken cancellationToken)
    {
        foreach (var error in actionContext.ModelState.SelectMany(kvp => kvp.Value.Errors))
        {
            var exception = error.Exception ?? new ArgumentException(error.ErrorMessage);
            //invoke global exception handling
        }

        return base.InvokeActionAsync(actionContext, cancellationToken);
    }
}
Run Code Online (Sandbox Code Playgroud)

这很糟糕,但它确实有效。这占据了我一天的大部分时间,我很高兴终于有所收获。

我很想知道这样做的后果是什么。Web API 中还有什么使用 ModelState 错误?有人可以在这个解决方案中添加一些可能的缺陷吗?