为输入参数避免"非可空类型的参数id的空条目"错误的清洁方法

Soo*_*ead 5 c# parameters asp.net-mvc

在ASP.NET MVC中,我非常喜欢它自动尝试从请求值填充Action参数的功能.

它使很多东西看起来非常干净,我的表格层次模型可以轻松地在那里旅行并通过电线返回.

但是它有一个恼人的问题.缺少非可空参数的自动异常.并不是框架错了.我理解这背后的原因,但是:

  1. 在很多情况下,我有一个int参数作为输入,其中请求一个特定对象(例如,产品的详细信息页面).
  2. 该参数是一个GET参数,因此它在url中可见,并且很容易更改.
  3. 如果用户更改了URL中的参数,则Web服务器会使用错误页面进行响应,并记录错误等.

这种错误应该在应用程序中很好地处理,我不需要用错误污染我的日志,对于这些情况也是404错误更合适恕我直言,因为没有标识符参数"无法找到资源".

我有一些关于如何避免这种情况的想法,但我想要一些透明的东西在一个地方处理它.

到目前为止,我所做的就是制作参数int?.

不是很透明,我需要ID.HasValue到处检查并明确抛出404.这污染了Action逻辑.

解决这个问题的最佳地点是什么?

编辑:

我还想指出,尽管抛出一个HttpException(404,"")仍然是一个例外,但由于浏览器搜索favicon等等,爬虫对恶意网址提出了大量请求,所有我的日志记录,警报等都是相应配置的.

Dav*_*lya 1

我认为这里合适的钩子是 ModelBinder。

您必须想出何时返回 404 的策略。根据上面的详细信息,为了简单起见,我将假设任何时候名为“id”的参数为 null 或未传递正如预期的那样,这会生成 404。以下是 ModelBinder 代码示例。

using System.Net;
using System.Web;
using System.Web.Mvc;

public class MyModelBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var result = base.BindModel(controllerContext, bindingContext);

        if (result == null && bindingContext.ModelName.ToLower() == "id")
        {
            throw new HttpException((int)HttpStatusCode.NotFound, null);
        }

        return result;
    }
}
Run Code Online (Sandbox Code Playgroud)

您将其连接到Global.asax

protected void Application_Start()
{
    ModelBinders.Binders.DefaultBinder = new MyModelBinder();
}
Run Code Online (Sandbox Code Playgroud)

为了获得更精细的效果,您可以仅向需要此行为的参数添加属性,并使用反射来检查该属性,并且在这种情况下仅抛出 404 异常,这会导致性能损失。因此,您可以根据需要仅为具有此行为的模型连接特定的 ModelBinder。或者,您也可以维护一个控制器/操作/参数的字典来应用该行为。

编辑:您还注意到您特别关心 GET 请求。该值在模型绑定器中可用:controllerContext.RequestContext.HttpContext.Request.HttpMethod.