0

I am trying to create a route that can allow for different formats (html/json/xml etc)

This is what I am trying, but it doesn't work.

routes.MapRoute(
          "Default",
          "{controller}/{action}/{id}/{format}",
          new { controller = "Home", action = "Index", id = UrlParameter.Optional, format = "html" },
          new { format = @"html|json" , id=@"\d+"}
       );

The routes that do work are these: /Person/details/1 /Person/details/1/json

But this don't work: /Person which imo should default to /Person/Index/html /Person/json and imo should lead to /Person/Index/json

But it doesn't match.

For the second of the ones that don't work I assume it thinks json is an action and that's the problem there, but for the first one I don't fully get it as I have defaults for each part of the url, and id is optional and it can't think html/json is the id as I say id have to be a number anyway, so it should imo get that one.

So who aren't the first one working?

For the second one I have been meaning to write a regex like this (I know it's not a real regex btw, any help on that is also appreciated..): action = @"!(html|json|\d+)" so that it will see that I'm not trying to say that json/html is an action, but that it then should use the default action of index.

But since the first one isn't even working I think I have to resolve that one first.

2
  • 1
    You would need another route that doesn't have the ID parameter. You mark it as options, but I'm not sure the parser is clever enough to know that you want to skip it. Commented Apr 18, 2011 at 10:03
  • @tomasmcguinness: Parse ir just as clever as you set it to be. For this kind of scenario route constraints should be used (you can check that in my answer). Commented Apr 18, 2011 at 10:24

2 Answers 2

1

The problem

Routes can have multiple optional parameters (although I suggest you don't use this unless you know Asp.net MVC routing very well), but you can't have non-optional parameters after optional ones as you've done it...

Imagine what would happen if you set a non-default "json" value for your format but don't provide id? What would come in place of the id? You'd run against a very similar problem with multiple optionals, hence I advise you not to use them.

Two solutions

  1. Change parameter order:

    "{controller}/{action}/{format}/{id}"
    
  2. Use two routes

    routes.MapRoute(
        "Ordering",
        "{controller}/{action}/{format}",
        new { controller = "Home", action = "Index", format = "html" },
        new { format = @"html|json|xml"}
    );
    
    routes.MapRoute(
        "Default",
        "{controller}/{action}/{id}/{format}",
        new { controller = "Home", action = "Index", format = "html" },
        new { format = @"html|json|xml", id = @"\d+"}
    );
    

    The first one will cover requests where ID is optional and you do provide format, and the second one will cover situations when ID is present.

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

1 Comment

Thanks, I went for solution 2, even though I need more routes, as I think the format at the end is the most logical. But to make /Person/json work I had to add another route: routes.MapRoute( "DefaultIndex", "{controller}/{format}", new { controller = "Home", action = "Index", format = "html" }, new { format = @"html|json|xml"} ); Unless I can add a regex that makes it understand that json in /person/json is not an action?
0

The id parameter cannot be optional. Only the last parameter of a route definition can be optional.

3 Comments

Or the last N parameters can be optinal. But there can't be any non-optional parameter after optinals.
@Robert Koritnik, if you have N optional parameters at the end the routing engine will have troubles distinguishing the routes. I know that there were some breaking changes in MVC 3 concerning this.
Why? It will work one by one. You do need to fully understand routing in order to make it work, because you will have to employ some constraints that will make this scenario working. But you're probably right that it's better to use parameters with defaults that make them seem (from URL perspective) that some of them are optional. Easier to understand and handle.

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.