HI WELCOME TO KANSIRIS

Custom Routes in ASP.NET MVC

Leave a Comment
ASP.NET MVC Routing is pretty flexible in itself and as demoed in Friendly URLs in ASP.NET Web Forms , we can mix and match old web forms style URLs with modern friendly URLs, even keeping both side by side. However, there are often quirks of implementation that need us to dig a little deeper for a solution.

Today we’ll pick an easy and superfluous reason to demonstrate how to do a custom RouteBase implementation. We will see how we can re-direct non-standard URLs like html/asp and aspx files to a cleaner ‘Friendly Url’ format. The Requirement is to handle extensions like html/pdf and redirect to Friendly URLs that ‘look like’ MVC generated URLs.
This can be done using a custom route.

The MVC Custom Route Implementation

We have to derive our own Route class from Route base and implement two methods:
1. GetRouteData: This method is called when Inbound URL Matching is required.
2. GetVirtualPath: This method is called when Outbound URL Generation is required
Step 1: To create a custom route base, we start off with a Basic Project template.
Step 2: Next we add a CustomRouteController to channel all the requests to. The controller simply puts the incoming URL in a label in our sample, but in reality, it could use the incoming URL and find out from a mapping database what the new equivalent URL was and do a RedirectPermanent action to a new Controller/ActionMethod too. That’s with the Controller.
public class CustomRouteController : Controller 

public ActionResult DirectCustomUrls(string customUrl) 

   if (customUrl.EndsWith("html")) 
   { 
    return new RedirectResult(customUrl); 
   } 
   else 
   { 
    ViewBag.ErrorMessage = "Unrecognized URL"; 
    return View(); 
   } 
}
}
Step 3: Now let’s setup the Custom Route. The constructor by design takes an array of valid URLs that we will have to pass when we are creating the route for this.
The GetRouteData method is called when a new request is made. In this method, the Requested path is checked to see if it contains any of the URLs that were passed in the constructor. If anyone matches, we send back the required RouteData, if not, we return Null and MVC takes the Route resolution to the next registered route.
Point to note is - the mechanism to verify the incoming Request Information matches the ‘custom requirements’ has to be in the GetRouteData method. Our oversimplistic scenario has resulted in a rather petty check involving string matching.
public override RouteData GetRouteData(HttpContextBase httpContext) 

RouteData result = null; 
string requestedURL = string.Empty; 
for (int i = 0; i < urls.Length; i++) 

   if (httpContext.Request.AppRelativeCurrentExecutionFilePath.Contains(urls[i])) 
   { 
    requestedURL = httpContext.Request.AppRelativeCurrentExecutionFilePath; 
    break; 
   } 
}     
if (!string.IsNullOrEmpty(requestedURL)) 

   result = new RouteData(this, new MvcRouteHandler()); 
   result.Values.Add("controller", "CustomRoute"); 
   result.Values.Add("action", "DirectCustomUrls"); 
   result.Values.Add("customUrl", requestedURL); 

return result; 
}
Step 4: Registering our Route -  We register our route as follows in the App_Data\RouteConfig.cs
public static void RegisterRoutes(RouteCollection routes) 

routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 
 routes.Add(new CustomRouteBase.Routing.CustomRouteBase( 
   "html", 
   "pdf"));
routes.MapRoute( 
   name: "Default", 
   url: "{controller}/{action}/{id}", 
   defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } 
); 
}
Essentially we are taking over all URLs that contain an html or pdf and redirecting via our Route. We add two default views for the Home Controller and the DynamicController. The DynamicController picks up the message from View Bag and displays it if any.
Let’s Run our app.
We initially are at the home page. Thereafter when we navigate to a random URL that ends with html we get redirected to our custom page via our CustomRouteBase.
aspnet-mvc-custom-route
Niceee.

Generating Outgoing URLs

Lets say now user needs to generate an HttpActionLink, to support this, we need to implement the GetVirtualPathmethod in our CustomRouteBase class. Once again, if we are unable to deal with the request, we let the routing system know by returning null. Otherwise, we return an instance of the VirtualPathData class.
public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values) 

     VirtualPathData result = null; 
     if (values.ContainsKey("html") || urls.Contains((string)values["html"], StringComparer.OrdinalIgnoreCase)) 
     { 
         result = new VirtualPathData(this, 
         new UrlHelper(requestContext) 
         .Content((string)values["html"]).Substring(1)); 
     } 
     return result; 
}
Now we place the following markup in our Index.cshtml
<div>This is a URL: 
@Html.ActionLink("Click me", "CustomUrl", 
new { html = "~/html/OldFile.html" }) 
</div>
This results in the following ActionLink getting generated
custom-route-outgoing
We can manipulate the generated link any way we want based on the final requirement.

Conclusion

With that we conclude this demo of how to Manipulate Route in ASP.NET MVC with a custom implementation of RouteBase.

0 comments:

Post a Comment

Note: only a member of this blog may post a comment.