Written by Irmak Tevfik on 28 - Jul - 2014

SEO friendly URL rewriting in MVC by keeping references in Database

Introduction
Aim of this article is to guide step by step approach to have search engine friendly and more readable URLs.
As an example such aim is to use
www.example.com/Data/this-is-a-test-article
rather than 
www.example.com/Data/1
to resolve the UniqueID of the object. So lets begin

Step 1: Creating Database Objects
We need to store every object (page) in the database. So lets create a table structure as


Description of the columns will be:
ID:​ Table Key
​PageURL: ​Will be the subject of the page
​PageSEOUrl: ​Will be the SEO url on the page  (eg www.example.com/Data/this-is-a-test)
​Controller: ​Controller which we need to navigate to
​Action: Action which we refer to
PageContent: ​Full page HTML content

So if we insert a dummy data, it will look like:

Currently we have done with the Database. Lets move to our MVC project.

Step 2: Custom routing configuration
We need to implement a custom routing to the project to resolve the given URL. So, Insert/Modify the RouteConfig.cs file under App_Start folder to have:
public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
 
        routes.MapRoute(
          "SEOFriendlyRoute",
          "Content/{SEOUrl}"
         ).RouteHandler = new UrlRouteHandler();
 
        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );
    }
}
the new route called "SEOFriendlyRoute" will navigate any URL following the path www.example.com/content/this-is-a-test ​to the class:
public class UrlRouteHandler : System.Web.Mvc.MvcRouteHandler
{
    EF.TESTEntities con = new TESTEntities();
    protected override IHttpHandler GetHttpHandler(System.Web.Routing.RequestContext requestContext)
    {
        var friendlyUrl = (string)requestContext.RouteData.Values["SEOUrl"];
        //after Detail/
        friendlyUrl = friendlyUrl.Substring(friendlyUrl.IndexOf('/') + 1);
         
        URLRewrite urlrewrite = null;
 
        if (!string.IsNullOrEmpty(friendlyUrl))
            urlrewrite = con.URLRewrites.Where(p => p.PageSEOUrl == friendlyUrl).FirstOrDefault();
 
        if (urlrewrite == null)
        {
            requestContext.RouteData.Values["controller"] = "Home";
            requestContext.RouteData.Values["action"] = "index";
        }
        else
        {
            requestContext.RouteData.Values["controller"] = urlrewrite.Controller;
            requestContext.RouteData.Values["action"] = urlrewrite.Action;
            requestContext.RouteData.Values["urlrewrite"] = urlrewrite;
        }
 
        return base.GetHttpHandler(requestContext);
    }
}

this class is derived from MvcRouteHandler and will override GetHttpHandler. Please note that Entity Framework is used in this example but you can implement any approach you like to resolve the URL.
In this approach:
1- Custom URL is gathered by var friendlyUrl = (string)requestContext.RouteData.Values["SEOUrl"]; 
2- Entity Framework is used to get matching URL from database by urlrewrite = con.URLRewrites.Where(p => p.PageSEOUrl == friendlyUrl).FirstOrDefault(); 
so in this example we have used www.example.com/Content/this-is-a-test-url ​which will match our data.
3. Matched data redirected to the given Controller and Action ​with given parameters

requestContext.RouteData.Values["controller"] = urlrewrite.Controller;
     requestContext.RouteData.Values["action"] = urlrewrite.Action;
     requestContext.RouteData.Values["urlrewrite"] = urlrewrite;
so we will have :
public class ContentController : Controller
{
    //
    // GET: /Content/
    public ActionResult Index(URLRewrite urlrewrite)
    {
        return View();
    }
}

and we should now have a simple approach for URL writing.








comments powered by Disqus