Identity Indexing Routing in ASP.NET MVC 4

I would like to support existing ASP.NET MVC 4 controller / action / id routing with the default controller = Home and default action = Index, but also include the controller / identifier to route to the controller index method if the second element is not a known action.

For example, given the Home controller with Index and Send actions:

/Home/Send -> controller Send method /Home -> controller Index method /Home/Send/xyz -> controller Send method with id = xyz /Home/abc -> controller Index method with id = abc 

However, if I first determine the route, it hides another. How can I do it?

+7
source share
6 answers

If the list of your actions (for example, Submit) is well known, and their names (actions) cannot coincide with some identifier value, we can use our custom ConstraintImplementation:

 public class MyRouteConstraint : IRouteConstraint { public readonly IList<string> KnownActions = new List<string> { "Send", "Find", ... }; // explicit action names public bool Match(System.Web.HttpContextBase httpContext, Route route , string parameterName, RouteValueDictionary values , RouteDirection routeDirection) { // for now skip the Url generation if (routeDirection.Equals(RouteDirection.UrlGeneration)) { return false; // leave it on default } // try to find out our parameters string action = values["action"].ToString(); string id = values["id"].ToString(); // id and action were provided? var bothProvided = !(string.IsNullOrEmpty(action) || string.IsNullOrEmpty(id)); if (bothProvided) { return false; // leave it on default } var isKnownAction = KnownActions.Contains(action , StringComparer.InvariantCultureIgnoreCase); // action is known if (isKnownAction) { return false; // leave it on default } // action is not known, id was found values["action"] = "Index"; // change action values["id"] = action; // use the id return true; } 

And the route map (before by default - both should be provided) should look like this:

 routes.MapRoute( name: "DefaultMap", url: "{controller}/{action}/{id}", defaults: new { controller = string.Empty, action = "Index", id = string.Empty }, constraints: new { lang = new MyRouteConstraint() } ); 

Summary In this case, we evaluate the value of the action parameter.

  • if both 1) action and 2) id are provided, we will not process it here.
  • and if it is a known action (listed or reflected ...).
  • only if the action name is unknown, change the route values: set the "Index" action and the action value for the ID.

NOTE: action names and id values โ€‹โ€‹must be unique ... then this will work

+2
source

Make the concrete first before the default default. Order matters.

 routes.MapRoute(name: "single", url: "{controller}/{id}", defaults: new { controller = "Home", action = "Index" }, constraints: new { id = @"^[0-9]+$" }); routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } ); 
+5
source

The easiest way is to simply create two Action methods in your controller. One for the index and one for sending and put your row id parameter on both. Since you cannot have repetitive or overloaded action methods, this solves this problem. Now your Index method will process both index and empty paths where id is present or not (null), and will process your views in this way. Your submit method will do the same as the index. Then you can route, process or redirect as you like, depending on whether the id is null. This should work unchanged in RouteConfig.cs:

 public ActionResult Index(string id) {if (id == null) Do A else Do B} public ActionResult Send(string id) {if (id == null) Do A else Do B} 

I had this fight for a long time, and it was the simplest solution.

+1
source

I donโ€™t think there is a solution for your requirements, since you have two competing routes. Perhaps you can define something specific (in case you have no other controllers).

 routes.MapRoute( name: "Send", url: "{controller}/Send/{id}", defaults: new { controller = "Home", id = UrlParameter.Optional } ); routes.MapRoute( name: "Home", url: "Home", defaults: new { controller = "Home", action = "Index" } routes.MapRoute( name: "Index", url: "{controller}/{id}", defaults: new { controller = "Home", action= "Index", id = UrlParameter.Optional } ); routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } ); 
0
source

This worked for me:

1) In RouteConfig, I put this on the first line:

 routes.MapRoute(name: "single", url: "{controller}/{lastName}", defaults: new { controller = "LeaveRequests", action = "Index" }); 

2) In my controller:

 public ViewResult Index(string lastName) { if (lastName == null) { return //return somthing } else { return //return something } } 

3) when the controller is called

 http://localhost:34333/leaveRequests/Simpsons 

He will provide you all requests for the Simpsons.

if you call http://localhost:34333/leaveRequests/ it will give all requests

0
source

it works for me

routes.IgnoreRoute ("{resource} .axd / {* PathInfo}");

  routes.MapRoute( name: "Default1", url: "{id}", defaults: new { controller = "Home", action = "Index" } ); routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } ); 
0
source

All Articles