ASP.NET MVC enum argument in controller mapping

≡放荡痞女 提交于 2019-12-07 03:01:18

问题


ASP.NET MVC provides simple templates for controller methods such as Details, and can have something like:

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

This can be accessed by: http://localhost:port/Controller/Details/id

What I'm trying to do is instead provide a different type like:

public enum MyEnum
{
    All,
    Pending,
    Complete
}

And then I setup my controller method like:

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

This works fine for: http://localhost:port/Controller/MyMethod/ because it uses the default argument.

To specify a different argument I have to do http://localhost:port/Controller/MyMethod?myEnum=All and that works.

I'm wondering, is it possible for me to be able to do http://localhost:port/Controller/MyMethod/All instead of using ?myEnum=All?

Upon trying to do it that way I get a 404 exception which is understandable, but why doesn't this happen for id in Details?

Can I change the MapRoute which is currently: url: "{controller}/{action}/{id}" to allow me to achieve it with my own type?

What I've tried so far:

I only want this route enforcement for one of my schemes such as http://localhost:port/Controller/MyMethod/{ViewType}, I tried this but it doesn't seem to do anything:

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

回答1:


/Controller/MyMethod/All will actually work. The problem is with the default route, which will consider All to be the id route parameter, which doesn't line up with what your action is using as a parameter. It would actually work fine if your action signature was:

public ActionResult MyMethod(MyEnum id = MyEnum.Pending)

Since it will then bind All to the right thing.

You could add another route for this use-case, but you'll need to be careful that you don't just create another "default" route, which will take over. In other words, you'll have to fix part of the 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 }
 );

Then, by the mere presence of the /Controller/ prefix to the route, it will use your custom route instead, and fill in All for the myEnum param, rather than hitting the default route and try to fill in id.

However, be advised that when using enums as route params, they must be exact matches. So, while /Controller/MyMethod/All will work, /Controller/MyMethod/all will not. To get around this, you'll have to create a custom model binder. I did a quick search and found the following article which may help you in that regard.




回答2:


You can indeed. Do not change the default route "{controller}/{action}/{id}", but rather add one before the default. This new one needs to be fairly specific:

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

What that basically says is "when you see request to literally Controller/MyMethod/whatever, use this controller and that method and pass whatever as parameter of the request". Note that actual controller does not necessary have to be what route says in the url, although it is a good idea to stick to that.



来源:https://stackoverflow.com/questions/42254852/asp-net-mvc-enum-argument-in-controller-mapping

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!