ASP.NET MVC
multiple parameters
routing
web development
URL parameters

Routing with Multiple `Parameters` using ASP.NET MVC

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

ASP.NET MVC maps URL segments to controller action parameters through its routing system. The default route {controller}/{action}/{id} handles a single parameter, but many applications need multiple parameters in URLs — for example /Products/List/Electronics/1/50 for category, page, and page size. You can define custom route templates, use attribute routing, query strings, or a combination to pass multiple parameters to controller actions.

Default Route (Single Parameter)

csharp
1// RouteConfig.cs
2routes.MapRoute(
3    name: "Default",
4    url: "{controller}/{action}/{id}",
5    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
6);
csharp
1// Matches: /Products/Details/42
2public class ProductsController : Controller
3{
4    public ActionResult Details(int id)
5    {
6        var product = db.Products.Find(id);
7        return View(product);
8    }
9}

The default route only handles one parameter (id). For multiple parameters, you need custom routes or attribute routing.

Custom Route with Multiple Parameters

csharp
1// RouteConfig.cs — add BEFORE the default route
2routes.MapRoute(
3    name: "ProductsByCategory",
4    url: "Products/{category}/{page}/{pageSize}",
5    defaults: new { controller = "Products", action = "List", page = 1, pageSize = 20 }
6);
csharp
1// Matches: /Products/Electronics/2/50
2public class ProductsController : Controller
3{
4    public ActionResult List(string category, int page = 1, int pageSize = 20)
5    {
6        var products = db.Products
7            .Where(p => p.Category == category)
8            .Skip((page - 1) * pageSize)
9            .Take(pageSize)
10            .ToList();
11
12        return View(products);
13    }
14}

Route order matters — MVC evaluates routes top to bottom and uses the first match.

csharp
1// Enable attribute routing in RouteConfig.cs
2public static void RegisterRoutes(RouteCollection routes)
3{
4    routes.MapMvcAttributeRoutes();  // Enable attribute routing
5    // ... default route below
6}
csharp
1public class ProductsController : Controller
2{
3    // /Products/Electronics/2/50
4    [Route("Products/{category}/{page:int}/{pageSize:int}")]
5    public ActionResult List(string category, int page = 1, int pageSize = 20)
6    {
7        return View();
8    }
9
10    // /Products/42/Reviews
11    [Route("Products/{productId:int}/Reviews")]
12    public ActionResult Reviews(int productId)
13    {
14        return View();
15    }
16
17    // /Products/2024/01/15
18    [Route("Products/{year:int}/{month:int}/{day:int}")]
19    public ActionResult ByDate(int year, int month, int day)
20    {
21        return View();
22    }
23}

Attribute routing places the route directly on the action method, making it easier to read and maintain than centralized route tables.

Route Constraints

csharp
1// Constrain parameters to specific types or patterns
2[Route("Products/{id:int}")]                    // id must be integer
3[Route("Users/{username:alpha}")]                // letters only
4[Route("Products/{id:min(1)}")]                  // minimum value
5[Route("Archive/{year:range(2000,2030)}")]       // range constraint
6[Route("Files/{filename:regex(^.*\\.pdf$)}")]    // regex constraint
7[Route("Api/{version:int:min(1):max(3)}")]       // multiple constraints
ConstraintExampleMatches
int{id:int}123, not abc
alpha{name:alpha}abc, not 123
bool{flag:bool}true, false
min(n){id:min(1)}1 and above
max(n){id:max(100)}100 and below
range(a,b){id:range(1,100)}1 to 100
length(n){code:length(5)}exactly 5 chars

Query String Parameters

Parameters not in the route template are automatically bound from the query string:

csharp
1// /Products/Search?q=laptop&minPrice=500&maxPrice=1500&sort=price
2public ActionResult Search(string q, decimal? minPrice, decimal? maxPrice, string sort = "relevance")
3{
4    var products = db.Products.Where(p => p.Name.Contains(q));
5
6    if (minPrice.HasValue)
7        products = products.Where(p => p.Price >= minPrice);
8    if (maxPrice.HasValue)
9        products = products.Where(p => p.Price <= maxPrice);
10
11    return View(products.ToList());
12}

Query strings are best for optional filters and search parameters where the URL should remain readable.

Mixing Route and Query Parameters

csharp
1// Route: /Products/Electronics?sort=price&page=2
2[Route("Products/{category}")]
3public ActionResult List(string category, string sort = "name", int page = 1)
4{
5    // category comes from the route
6    // sort and page come from the query string
7    return View();
8}

Model Binding with Complex Parameters

csharp
1public class ProductFilter
2{
3    public string Category { get; set; }
4    public decimal? MinPrice { get; set; }
5    public decimal? MaxPrice { get; set; }
6    public string Sort { get; set; } = "name";
7    public int Page { get; set; } = 1;
8}
9
10// /Products/Filter?Category=Electronics&MinPrice=100&Sort=price&Page=2
11public ActionResult Filter(ProductFilter filter)
12{
13    // All query parameters are bound to the model automatically
14    var products = db.Products
15        .Where(p => p.Category == filter.Category)
16        .OrderBy(filter.Sort)
17        .Skip((filter.Page - 1) * 20)
18        .Take(20);
19
20    return View(products.ToList());
21}

Generating URLs with Multiple Parameters

csharp
1// In Razor views
2@Url.Action("List", "Products", new { category = "Electronics", page = 2, pageSize = 50 })
3// /Products/Electronics/2/50 (if matching route exists)
4// /Products/List?category=Electronics&page=2&pageSize=50 (falls back to query string)
5
6@Html.ActionLink("Page 2", "List", "Products", new { category = "Electronics", page = 2 }, null)

Common Pitfalls

  • Route order matters: MVC matches the first route that fits the URL. If the default route {controller}/{action}/{id} comes before your custom route, it may capture the URL first. Always place more specific routes before generic ones.
  • Parameter name mismatch: The route template parameter name ({category}) must match the action method parameter name (string category). A mismatch causes the parameter to be null or trigger a 404.
  • Missing route constraints: Without constraints, /Products/Details/abc matches {id} even if the action expects an int, causing a runtime error. Add {id:int} constraints to reject non-matching URLs early with a 404.
  • Forgetting to enable attribute routing: [Route] attributes are ignored unless routes.MapMvcAttributeRoutes() is called in RouteConfig.cs. Without it, only convention-based routes work.
  • Ambiguous routes: Two routes that match the same URL pattern cause an AmbiguousMatchException. Use constraints or different URL structures to disambiguate.

Summary

  • The default route handles one parameter — add custom routes for multiple parameters
  • Attribute routing ([Route]) is more readable than centralized MapRoute definitions
  • Use route constraints ({id:int}, {name:alpha}) to validate parameters in the URL
  • Use query strings for optional filters and search parameters
  • Model binding automatically maps query string parameters to complex objects
  • Place specific routes before generic ones — MVC uses first-match ordering

Course illustration
Course illustration

All Rights Reserved.