Applications

Human Friendly MVC URLs

Overview   
The out-of-the-box MVC URL is not very readable to the end user. It usually looks like http://{domain}/{controller}/{action}/{id}, where the {id} is an integer matching the object in the database. Appending a ‘slug’ to the {id} is a quick, low-impact fix that greatly increases readability. The term slug comes from newspaper editing referring to a short name given to an article or story (http://en.wikipedia.org/wiki/Semantic_URL). Implementation is as easy as adding a route configuration and modifying the URLs.

Route Configuration

Order matters in MVC route configs. The more specific the route, the higher it should be on the list. In the RouteConfig.cs file in the App_Start folder, add the following route above the default.
routes.MapRoute(
    name: "SlugUrl",
    url: "MyPath/{id}-{slug}",
    defaults: new { controller = "MyController", action = "MyAction" }
);
Notice that ‘MyPath’ is a fixed value for this URL (it is not in bracers, so it’s not considered a route value), you could replace this with whatever because the actual controller and action are specified in the ‘defaults’ parameter. The hyphen between the {id} and {slug} route values is crucial. The hyphen delimits the route values. This also means that the {slug} cannot contain any hyphens, or else MVC will think it’s another route value.

Modify the URLs

Pass the view a ‘slugified’ version of the object’s title and use that to construct the URL appropriately, it must match the route config (in this case http://{domain}/MyPath/{id}-{slug}).
public static string Slugify(string title)
{
    string str = title.ToLower();
    // get rid of hyphens so the route doesn’t break
    str = str.Replace("-", " ");
    // invalid chars          
    str = Regex.Replace(str, @"[^a-z0-9\s-]", "");
    // convert multiple spaces into one space  
    str = Regex.Replace(str, @"\s+", " ").Trim();
    // cut and trim
    str = str.Substring(0, str.Length <= 45 ? str.Length : 45).Trim();
    str = Regex.Replace(str, @"\s", "_");  
    return str;
}
Then construct the URL in the view.
<a class="My-Class" href="/MyPath/@Model.Id@Model.Slug">My Slugified Link</a>
Notice that we didn’t have to fix anything in the controller, MVC will automatically bind whatever comes before the hyphen in the URL to the {id} route value. The beauty here is that since we’re only going off the object’s Id, if the title ever changes we’ll still be in good shape.

Leave a Reply