Search code examples
c#asp.net-mvcasp.net-mvc-4asp.net-mvc-routing

MVC4 Error-No route in the route table matches


I am new to programming with C# and MVC4 the error happens at

@{ 
  Html.RenderAction("Menu", "Nav"); 
} 

It is coming back with an error stating that there is no route in the route table matches the supplied values. I have tried searching the internet to no avail, any help would be greatly appreciated. Thanks

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width" />
    <title>@ViewBag.Title</title>
    <link href="~/Content/Site.css" type="text/css" rel="stylesheet" />
</head>
<body>
   <div id="header">
       <div class="title">Bag Labels</div>
   </div>
    <div id="categories">
        @{ Html.RenderAction("Menu", "Nav"); }
    </div>
    <div id="content">
         @RenderBody()
    </div>
</body>
</html>

This is the _Layout.cshtml

Here is my NavController.cs

using NavisionStore.Domain.Abstract;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace NavisionStore.WebUI.Controllers
{
    public class NavController : Controller
    {
        private IProductRepository repository;

        public NavController(IProductRepository repo)
        {
            repository = repo;
        }
        public PartialViewResult Menu(string category = null)
        {
            ViewBag.SelectedCategory = category;

            IEnumerable<string> categories = repository.Products
                .Select(x => x.Category)
                .Distinct()
                .OrderBy(x => x);

            return PartialView(categories);  
        }
    }
}

Here is my RouteConfig.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

namespace NavisionStore.WebUI
{
    public class RouteConfig
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(null,
                "",
                new { 
                    controller = "Product", action = "List",
                    category = (string)null, page = 1
                }
            );

            routes.MapRoute(null,
                "Page{page}",
                new { controller = "Product", action = "List", category = (string)null },
                new { page = @"\d+" }
            );

            routes.MapRoute(null,
                "{category}",
                new { controller = "Product", action = "List", page = 1 }
        );

            routes.MapRoute(null,
                "{category}/Page{page}",
                new { controller = "Product", action = "List" },
                new { page = @"\d+" }
        );

            routes.MapRoute(null, "{contoller}/{action}");
        }
    }
}

Here is my ProductController.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using NavisionStore.Domain.Abstract;
using NavisionStore.Domain.Entities;
using NavisionStore.WebUI.Models;



namespace NavisionStore.WebUI.Controllers
{
    public class ProductController : Controller
    {
        private IProductRepository repository;
        public int PageSize = 1;

        public ProductController(IProductRepository productRepository)
        {
            this.repository = productRepository;
        }

        public ViewResult List(string category, int page = 1)
        {
            ProductsListViewModel ViewModel = new ProductsListViewModel
            {
                Products = repository.Products
                .Where(p => category == null || p.Category == category)
                .OrderBy(p => p.Id)
                .Skip((page - 1) * PageSize)
                .Take(PageSize),
                 PagingInfo = new PagingInfo
                {
                    CurrentPage = page,
                    ItemsPerPage = PageSize,
                    TotalItems = repository.Products.Count()
                },
                CurrentCategory = category
            };

            return View(ViewModel);
        }
    }
}

Solution

  • Remove the following routes from your routing config:

    routes.MapRoute(null,
         "",
         new { 
            controller = "Product", action = "List",
            category = (string)null, page = 1
        }
    );
    
    
    routes.MapRoute(null, "{contoller}/{action}");
    

    Also, the following routes are likely not doing what you are expecting, as each one is actually returning the same controller/action for each matching url. I recommend removing them.

    routes.MapRoute(null,
                "Page{page}",
                new { controller = "Product", action = "List", category = (string)null },
                new { page = @"\d+" }
            );
    
            routes.MapRoute(null,
                "{category}",
                new { controller = "Product", action = "List", page = 1 }
        );
    
            routes.MapRoute(null,
                "{category}/Page{page}",
                new { controller = "Product", action = "List" },
                new { page = @"\d+" }
        );
    

    They could be replaced with the following:

    routes.MapRoute(
       "Page",
       "Product/List/{category}/{page}",
       new { controller = "Product", action = "List", page = UrlParameter.Optional },
       new { page = @"\d*" }
    );
    

    Finally, add names to all of your routes, not null. Currently, the only one you have named is "default".

    In the end, you should be at a much simpler routing configuration for what you are trying to do:

    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    
    // matches:
    // product/list/unicorns
    // product/list/carrots/15
    routes.MapRoute(
       "Page",
       "Product/List/{category}/{page}",
       new { controller = "Product", action = "List", page = UrlParameter.Optional },
       new { page = @"\d*" } //<-- note the asterisk here
    );
    
    routes.MapRoute(
                "Default",
                "{controller}/{action}/{id}",
                new {controller = "Product", action = "List",
                id = UrlParameter.Optional
    }