Custom Routes in ASP.NET MVC
Posted by: Suprotim Agarwal ,
on 1/22/2014,
in
Category ASP.NET MVC
Abstract: Learn how to use Custom RouteBase class in ASP.NET MVC to manipulate incoming and outgoing URLs based on specific relation and criteria.
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.
Side Note: For those interested, ASP.NET MVC 5 has introduced AttributeRouting. You can read more about it in the 10th edition of the DNC .NET Magazine
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.
Niceee.
Generating Outgoing URLs
Lets say now user needs to generate an
HttpActionLink, to support this, we need to implement the
GetVirtualPath method 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
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.
This article has been editorially reviewed by Suprotim Agarwal.
C# and .NET have been around for a very long time, but their constant growth means there’s always more to learn.
We at DotNetCurry are very excited to announce The Absolutely Awesome Book on C# and .NET. This is a 500 pages concise technical eBook available in PDF, ePub (iPad), and Mobi (Kindle).
Organized around concepts, this Book aims to provide a concise, yet solid foundation in C# and .NET, covering C# 6.0, C# 7.0 and .NET Core, with chapters on the latest .NET Core 3.0, .NET Standard and C# 8.0 (final release) too. Use these concepts to deepen your existing knowledge of C# and .NET, to have a solid grasp of the latest in C# and .NET OR to crack your next .NET Interview.
Click here to Explore the Table of Contents or Download Sample Chapters!
Was this article worth reading? Share it with fellow developers too. Thanks!
Suprotim Agarwal, MCSD, MCAD, MCDBA, MCSE, is the founder of
DotNetCurry,
DNC Magazine for Developers,
SQLServerCurry and
DevCurry. He has also authored a couple of books
51 Recipes using jQuery with ASP.NET Controls and
The Absolutely Awesome jQuery CookBook.
Suprotim has received the prestigious Microsoft MVP award for Sixteen consecutive years. In a professional capacity, he is the CEO of A2Z Knowledge Visuals Pvt Ltd, a digital group that offers Digital Marketing and Branding services to businesses, both in a start-up and enterprise environment.
Get in touch with him on Twitter @suprotimagarwal or at LinkedIn