Search code examples
asp.net-mvcroutesasp.net-mvc-5custom-attributesslug

How to set a slug for a route attribute?


I have an action like this:

[HttpGet]
[Route("~/books/{id:int:min(1)}/{slug?}")]
public ActionResult Book(int? id, string slug)
{
    if (slug == null)
    {
        slug = "awesome-book";
        return RedirectToAction("Book", new { id, slug });
    }

    etc.
}

The problem is that the new route is generated like 'books/1?slug=awesome-book' and that's not what I wanted but 'books/1/awesome-book'. How can I properly set the slug?


Solution

  • This is a problem with generating route URLs. Since the slug route param is optional, the routing framework stops at /books/1 and then tacks on any params not covered by the URL as a query string, which in this case includes slug. This is due to the short circuiting system the routing framework employs and there's really nothing you can do about it.

    There is a workaround, though. If instead of using an optional param, you use another route, you can name that route and then reference it explicitly. For example:

    [Route("~/books/{id:int:min(1)}", Order = 1)]
    [Route("~/books/{id:int:min(1)}/{slug}", Order = 2, Name = "BookWithSlug")]
    

    Then, you can generate the URL with:

    return RedirectToRoute("BookWithSlug", new { id, slug });
    

    And, you'll end up with the URL you want.