【问题标题】:ASP.NET MVC2 Route Constraint - optional number id parameterASP.NET MVC2 Route Constraint - 可选数字 id 参数
【发布时间】:2011-05-23 04:30:12
【问题描述】:

我在我的 ASP.NET MVC2 项目中设置了默认路由,并希望为我的其他一些控制器添加/修改它。假设我有一个带有 Details 操作的 Customer 控制器,该控制器期望和“id”参数(int)。例如:

    //
    // GET: /Customer/Details/5
    public ActionResult Details(int id)
    {
      //...
    }

如果用户输入“非数字”,如何添加将返回 404 的路由? 我尝试添加以下“之前”默认路由,但它不起作用......

    routes.MapRoute(
        "DefaultDigitsId", // Route name
        "{controller}/{action}/{id}", // URL with parameters
        new { controller = "Home", action = "Index" },
        new { id = @"\d+" }
        );

    routes.MapRoute(
        "Default", // Route name
        "{controller}/{action}/{id}", // URL with parameters
        new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
        );

注意,如果可能的话,我希望保留默认路由... 我所有的控制器都使用“详细信息”和“编辑”,其中需要“id”(int)参数。 我想知道是否有一种方法可以在不必指定多个路由的情况下完成此操作(即通用的)...当然,目标是如果用户输入类似“/Customer/Details/apple”之类的内容,它不会抛出一个错误但将它们带到错误页面...

还有this post 提示设置默认值,但我不知道该怎么做...

【问题讨论】:

  • 所以“Customer/Details/1”应该使用 DefaultDigitsId 路由,“Customer/Details/apple”应该给你一个 404,对吧?您希望哪些 URL 使用您的默认路由?
  • 我猜是 /Customer/Index 或 /Customer/Create 之类的...不过我明白您的意思...您是否暗示我可以从默认路由中删除“id”,因为它不会有用吗?
  • 我并没有真正想表达观点:只要理解你想要的行为。

标签: asp.net-mvc asp.net-mvc-2 constraints custom-routes


【解决方案1】:

我还没有尝试过,但您可能想尝试一下:

routes.MapRoute(
    "DefaultDetails",
    "{controller}/Details/{id}",
    new { controller = "Home", action = "Details" },
    new { id = @"\d+" }
    );

routes.MapRoute(
    "DefaultEdit",
    "{controller}/Edit/{id}",
    new { controller = "Home", action = "Edit" },
    new { id = @"\d+" }
    );

routes.MapRoute(
    "Default",
    "{controller}/{action}/{id}",
    new { controller = "Home", action = "Index", id = UrlParameter.Optional }
    );

我希望“Customer/Details/1”使用第一个路由(它将 id 验证为数字,对“Customer/Edit/1”的调用使用第二个,同样如此,以及对“ Customer/Buy/Orange" 使用第三条路线,它不会尝试以这种方式验证 ID。我了解您要正确执行的操作吗?如果这种方法有效,请告诉我。

【讨论】:

  • 好的。您的方法比具有约束的路由(与默认路由相同,但 id 与正则表达式匹配)并具有默认路由但从中删除 id 更好一点。谢谢
【解决方案2】:

在匹配数字 id 之后添加一个 IgnoreRoute,它将忽略对 Customer 控制器上 Details 操作的任何请求:

routes.MapRoute(
  "DefaultDigitsId", // Route name
  "{controller}/{action}/{id}", // URL with parameters
  new { controller = "Home", action = "Index" },
  new { id = @"\d+" } // match numeric id
);

routes.IgnoreRoute("Customer/Details/{*pathInfo}");

routes.MapRoute(
  "Default", // Route name
  "{controller}/{action}/{id}", // URL with parameters
  new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);

【讨论】:

  • 我是否必须为所有其他操作和控制器添加忽略...大约有 5 个控制器,每个控制器至少有 2 个需要“id”的操作...而且它会增长...跨度>
  • 如果您只想接受数字的 id,只需从“默认”路由中去掉“/{id}”
  • lol:) 与我一秒钟前在@StriplingWarrior 回复评论时的想法完全相同
【解决方案3】:

任何无法解析为字符串的值都会在调用时使 id 值为 null,因此如果 id 不为 null,您可以重定向到错误页面。

另一种可能性是注册一个全局过滤器,检查是否有一个名为 id 的参数,如果它为空,则重定向到错误页面

【讨论】:

  • 当 id 参数未声明为可空时,如何检查它是否为空?此外,我希望我不必将它声明为“int?id”,这样我就可以检查它是否为空(然后也尝试解析它)......
  • 你说得对,我没有注意到这一点。它使用int?或上面发布的其他解决方案
  • 我认为将参数声明为int?将是较小的弊端,因为这将允许路由系统完成其工作。在您的控制器中,当值为 null 未找到的数值时,您需要返回错误。考虑到您很可能需要验证 int 值以查看它是否是有效 ID,这可能不是一个坏方法。
  • @Hector 我不得不恭敬地不同意你的观点:) 将参数标记为可空,以便您可以测试其有效性,在我看来,应该是框架的“工作”。我确实有基于 id 获取客户的业务服务,如果没有找到,我可以在控制器中捕获业务异常 (CustomerNotFoundException)。但那是“业务级别验证”而不是“mvc 参数验证”......单独的关注点......
  • @zam6ak 也许您可以与开发 MVC 框架的人分享这一点,我认为您的观点是有效的。例如,在 Play!框架(一个Java MVC框架)如果值无法解析,路由器返回错误。
猜你喜欢
  • 1970-01-01
  • 2015-01-28
  • 2017-05-02
  • 2016-11-04
  • 2011-03-12
  • 2012-08-08
  • 1970-01-01
  • 2011-07-21
  • 1970-01-01
相关资源
最近更新 更多