Search code examples
c#asp.net-mvcroutesslug

C# Mvc Generic Route using Slug


I'm trying to create a generic route to work with slugs, but I always got an error

The idea is, instead of www.site.com/controller/action I get in the url a friendly www.site.com/{slug}

e.g. www.site.com/Home/Open would be instead www.site.com/open-your-company

Error

server error in '/' application The Resource cannot be found

In my Global.asax I have

public static void RegisterRoutes(RouteCollection routes)
{
    //routes.Clear();
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute("DefaultSlug", "{slug}", new { controller = "Home", action = "Open", slug = "" });
    routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}/{id}",
        defaults: new
        {
            area = "",
            controller = "Home",
            action = "Index",
            id = UrlParameter.Optional,
            slug = ""
        }
    );
}

In one of my cshtml I have the following link (even when it's commented, there is still the same error).

@Html.ActionLink("Open your company", "DefaultSlug", new { controller = "Home", action = "Open", slug = "open-your-company" })

EDIT: HomeController

public ActionResult Open() { 
    return View(new HomeModel()); 
}

Solution

  • In Global.asax you slug can not be empty,if empty ,the url will be not go to the default route

    public static void RegisterRoutes(RouteCollection routes)
    {
        //routes.Clear();
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    
        routes.MapRoute(
            name: "DefaultSlug",
            url: "{slug}",
            defaults: new { controller = "Home", action = "Open" },
            constraints: new{ slug=".+"});
    
        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new
            {
                area = "",
                controller = "Home",
                action = "Index",
                id = UrlParameter.Optional
            }
        );
    }
    

    And update the HomeController

    public ActionResult Open(string slug) {
        HomeModel model = contentRepository.GetBySlug(slug);
    
        return View(model); 
    }
    

    Testing Route link...

    @Html.RouteLink("Open your company", routeName: "DefaultSlug", routeValues: new { controller = "Home", action = "Open", slug = "open-your-company" })
    

    and Action link...

    @Html.ActionLink("Open your company", "Open", routeValues: new { controller = "Home", action = "Open", slug = "open-your-company" })
    

    both produces...

    http://localhost:35979/open-your-company