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" }
);
/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.
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.