【问题标题】:ASP.NET MVC enum argument in controller mapping控制器映射中的 ASP.NET MVC 枚举参数
【发布时间】:2017-07-04 10:29:13
【问题描述】:

ASP.NET MVC 为控制器方法提供了简单的模板,例如Details,并且可以有类似的东西:

public ActionResult Details(int id)
{
    // do something
}

可以通过以下方式访问:http://localhost:port/Controller/Details/id

我想要做的是提供不同的类型,例如:

public enum MyEnum
{
    All,
    Pending,
    Complete
}

然后我设置我的控制器方法,如:

public ActionResult MyMethod(MyEnum myEnum = MyEnum.Pending)
{
    // do something
}

这适用于:http://localhost:port/Controller/MyMethod/,因为它使用默认参数。

要指定不同的参数,我必须执行 http://localhost:port/Controller/MyMethod?myEnum=All 并且有效。

我想知道,我是否可以使用http://localhost:port/Controller/MyMethod/All 而不是使用?myEnum=All

在尝试这样做时,我得到了一个 404 异常,这是可以理解的,但是为什么 Details 中的 id 不会发生这种情况?

我可以更改MapRoute(当前为:url: "{controller}/{action}/{id}")以允许我使用自己的类型来实现它吗?

到目前为止我已经尝试过:

我只想为我的一个方案(例如http://localhost:port/Controller/MyMethod/{ViewType})执行此路由,我尝试了this,但它似乎没有做任何事情:

routes.MapRoute(
    "MyRoute",
    "MyController/Index/{MyEnum}",
    new { controller = "MyController", action = "Pending" }
);

【问题讨论】:

  • 是的。但是,您应该添加一条新路线来处理这种情况。

标签: c# asp.net asp.net-mvc routeconfig


【解决方案1】:

确实可以。不要更改默认路由"{controller}/{action}/{id}",而是在默认前添加一个。这个新的需要相当具体:

routes.MapRoute(
    "EnumRoute",
    "Controller/MyMethod/{myEnum}",
    new { controller = "Controller", action = "MyMethod", myEnum = UrlParameter.Optional }
);

基本上说的是“当您看到对 Controller/MyMethod/whatever 的请求时,请使用此控制器和该方法并将任何内容作为请求的参数传递”。请注意,实际控制器不一定必须是 url 中所说的路由,尽管坚持这一点是个好主意。

【讨论】:

  • 我还需要在MyMethod 中设置默认的MyEnum 参数吗?另外,我试过这个,但它似乎没有做任何事情,它只强制执行默认参数。
【解决方案2】:

/Controller/MyMethod/All 实际上会起作用。问题在于默认路由,它将All 视为id 路由参数,它与您的操作用作参数的内容不一致。如果你的动作签名是:

public ActionResult MyMethod(MyEnum id = MyEnum.Pending)

因为它会将All 绑定到正确的东西。

可以为此用例添加另一个路由,但您需要注意不要创建另一个“默认”路由,它将接管。换句话说,您必须修复部分 URL:

routes.MapRoute(
    "MyCustomRoute",
    "Controller/{action}/{myEnum}",
    new { controller = "Controller", action = "MyMethod", myEnum = MyEnum.Pending }
);

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

然后,由于路由仅存在 /Controller/ 前缀,它将使用您的自定义路由,并为 myEnum 参数填写 All,而不是点击默认路由并尝试填写在id

但是,请注意,当使用枚举作为路由参数时,它们必须是精确匹配。所以,虽然/Controller/MyMethod/All 可以工作,但/Controller/MyMethod/all 不会。为了解决这个问题,您必须创建一个自定义模型绑定器。我进行了快速搜索,发现以下article 可能在这方面对您有所帮助。

【讨论】:

  • 这行得通,我的后续问题是:如果我将MyMethod 设置为:public ActionResult MyMethod(MyEnum id= MyEnum.Pending) 是否等同于不强制执行自定义MapRoute?此外,如果myEnum 为空,那么您拥有myEnum = MyEnum.Pending 的位置是默认值吗?所以我可以从我的控制器中删除默认参数?
  • 关于区分大小写,我的控制器似乎很好。即使到了/Controller/MyMethod/cOmPLeTe,也不确定那里发生了什么。
  • 这两个默认值用于不同的事物。如果 URL 中根本没有提供参数,则路由默认值。动作签名的默认值是在提供的值由于某种原因无法绑定的情况下。
  • 在 MVC 的更新中可能已经解决了区分大小写的问题。如果它适合你,那就太好了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多