Nikolaj Thorup Jensen Nikolaj Thorup Jensen - 14 days ago 5
C# Question

Multiple Parameters MVC routing

I am making a library-like website. In this library an article can have a category, and said category can have up to 2 parent categories, like: "World > Country > City".

I want to keep all the displaying of views to a single Controller for all articles, named

LibraryController
. And the 2 actions being used are
Article(string id)
and
Category(string[] ids)


To view an article called "The Templar Order" the user must input:
/library/article/the-templar-order


Alright, so now the categories. I have 2 approaches in my head, this example is to view the "City" category:


  1. The simple approach:
    /library/world-country-city

  2. The one I would like:
    /library/world/country/city

  3. The one I do NOT want, as it becomes too clumsy:
    /library/category/world/country/city



But I am a bit confused as to how I would go about creating a route that takes 3 parameters and essentially no action. And except for the first parameter "world" the rest should be optional, like this:
"/library/world/"
>
"/library/world/country/"
>
"/library/world/country/city/"


So how would I go about creating such a route ?

Solution

RouteConfig.cs

// GET library/article/{string id}
routes.MapRoute(
name: "Articles",
url: "Library/Article/{id}",
defaults: new { controller = "Library", action = "Article", id = "" }
);

// GET library/
routes.MapRoute(
name: "LibraryIndex",
url: "Library/",
defaults: new { controller = "Library", action = "Index" }
);

// GET library/category/category/category etc.
routes.MapRoute(
name: "Category",
url: "Library/{*categories}",
defaults: new { controller = "Library", action = "Category" }
);

Answer

You can achieve that with the following two routes.

// GET library/article/the-templar-order
routes.MapRoute(
     name: "Articles",
     url: "Library/Article/{id}",
     defaults: new { controller = "Library", action = "Article" }
 );

// GET library/world/country/city
routes.MapRoute(
     name: "Category",
     url: "Library/{*categories}",
     defaults: new { controller = "Library", action = "Category" }
 );

And a slight modification to the target action

public ActionResult Category(string categories) {
    categories = categories ?? string.Empty;
    var ids = categories.Split(new []{'/'}, StringSplitOptions.RemoveEmptyEntries);
    //...other code
}