1

can I have domain.com/action/id as well as domain.com/controller/action?

how would I register these in the route-table?

2 Answers 2

2

Is ID always guaranteed to be a number? If yes, then you could use RouteConstraints:

routes.MapRoute("ActionIDRoute",
               "{action}/{id}",
               new { controller = "SomeController" },
               new {id= new IDConstraint()});
routes.MapRoute("ControllerActionRoute",
                "{controller}/{action}",
                new {}); // not sure about this last line

The IDConstraint class looks like this:

public class IDConstraint : IRouteConstraint
{
    public bool Match(HttpContextBase httpContext, Route route,
                      string parameterName, RouteValueDictionary values,
                      RouteDirection routeDirection)
    {
        var value = values[parameterName] as string;
        int ID;
        return int.TryParse(value,out ID);
    }
}

Basically what is happening is that you have two identical routes here - two parameters, so it's ambigous. Route Constraints are applied to parameters to see if they match.

So:

  1. You call http://localhost/SomeController/SomeAction
  2. It will hit the ActionIDRoute, as this has two placeholders
  3. As there is a constraint on the id parameter (SomeAction), ASP.net MVC will call the Match() function
  4. As int.TryParse fails on SomeAction, the route is discarded
  5. The next route that matches is the ControllerActionRoute
  6. As this matches and there are no constraints on it, this will be taken

If ID is not guaranteed to be a number, then you have the problem to resolve the ambiguity. The only solution I am aware of is hardcoding the routes where {action}/{id} applies, which may not be possible always.

Sign up to request clarification or add additional context in comments.

3 Comments

well, id is guaranteed to be a number for now, but who knows when the project expands, if you know what I mean.
@progtick Indeed, but that could become a problem. As said, your issue is that you have two equal routes, that is: 2 routes that look the same as they have the same format and the same number of placeholders. The name of the Placeholders doesn't matter, but you somehow need to differentiate between them. RouteConstraints are one way if you know that the semantics are always different (ID is always a number & Action is never a number, or ID always starts with i_ & action never starts with i_). The other option: Change your routing completely to not have similar routes.
I agree. I will ponder over this. In the meanwhile, your solution of using constraint works for me.
1

Yes, you can add a new rule above the default rule and provide a default value for the controller.

routes.MapRoute(
  "MyRole",  // Route name
  "{action}/{id}",  // URL with parameters
  new { controller = "Home", action = "Index", id = "" } // Parameter defaults
);

The sample routs all actions to the "Home" controller.

1 Comment

and what rule would take care of the domain.com/controller/action route? I have AccountController that has LogOn actionresult defined. However, domain.com/account/logon is not being catched by the routetable.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.