ASP.NET 控制器映射中的 MVC 枚举参数

ASP.NET MVC enum argument in controller mapping

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 没有发生这种情况?

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

到目前为止我尝试过的:

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

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

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

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

基本上说的就是"when you see request to literally Controller/MyMethod/whatever, use this controller and that method and pass whatever as parameter of the request"。请注意,实际控制人不一定必须是 url 中所说的路线,尽管坚持这一点是个好主意。

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

,它实际上可以正常工作
public ActionResult MyMethod(MyEnum id = MyEnum.Pending)

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

可以为此use-case添加另一条路线,但您需要注意不要只是创建另一条"default"路线, 它将接管。换句话说,您必须修复 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,可能会在这方面对您有所帮助。