if you don't like a way Routing system handle route you can create your own way to handle route by deriving class from RouteBase this give you control over how url matched and how url parameter extracted. you have to implement two method for handle request.
- GetRouteData:This is mechanism by which inbound url work.This method call on each route of RouteCollection until one of them return non-null value.
- GetVirtualPath:This is method is responsible for generating Outbound url.This method call on each route in RouteCollection until one of them return non-null value.
for demonstration purpose we create a class that handle legacy url request. this is used when some user bookmarked page url of our site and we made changes to our url or directory structure some url would be broken but we still want that user bookmark works well. for that we have to create some system that redirect old url to our sites original url. i am going to demonstrate that small mechanism.
Public Class LegacyController Inherits System.Web.Mvc.Controller ' ' GET: /Legacy Function Index(ByVal legacyurl As String) As ActionResult Return View(CObj(legacyurl)) End Function End Class
above code we have just create simple controller that handle request of legacy url,for demonstration purpose we just pass that url to Index view for display,we have convert string to object for tell the helper method that we are going to pass parameter for model not for ViewName.
for handling legacy url we have to create custom route which contain logic that redirect request to out legacy controller.
Public Class LegacyRoute Inherits RouteBase Private oldurls() As String Sub New(ByVal ParamArray urls() As String) oldurls = urls End Sub Public Overrides Function GetRouteData(httpContext As System.Web.HttpContextBase) As System.Web.Routing.RouteData Dim result As RouteData = Nothing Dim requestedUrl As String = httpContext.Request.AppRelativeCurrentExecutionFilePath If oldurls.Contains(requestedUrl, StringComparer.OrdinalIgnoreCase) Then result = New RouteData(Me, New MvcRouteHandler) result.Values.Add("controller", "Legacy") result.Values.Add("action", "Index") result.Values.Add("legacyUrl", requestedUrl) End If Return result End Function Public Overrides Function GetVirtualPath(requestContext As System.Web.Routing.RequestContext, values As System.Web.Routing.RouteValueDictionary) As System.Web.Routing.VirtualPathData Dim routedata As VirtualPathData = Nothing If values.ContainsKey("legacyUrl") AndAlso oldurls.Contains(values("legacyUrl").ToString, StringComparer.OrdinalIgnoreCase) Then routedata = New VirtualPathData(Me, New UrlHelper(requestContext).Content(values("legacyUrl").ToString).Substring(1)) End If Return routedata End Function End Class
each and every route is derived from RouteBase class.so we create custom LegacyRoute class and derived it from RouteBase.
we create constructor that accept string array that should contain list of oldurls
and in GetRouteData function we get a requested URL using AppRelativeCurrentExecutionFilePath property of Request object.
and check that oldurls contain requested url if so then we create new instance of RouteData and add values for its controller,action,legacyUrl parameter that point to our
LegacyController's Index action and pass legacy url as action parameter. and return instance of routedata.
as i mention at the starting of this post GetVirtualPath function is responsible for generating out going url.we
also follow the same logic for generating outgoing url.when html helper method ask for url and route match for that request GetVirtualPath
function called. inside it we check that values contain key legacyUrl and that and our oldurl array contain that legacy url.if so then
we create new instance of VirtualPathData from current RouteBase and new UrlHelper that contain legacyurl.
in the end we use SubString(1) for strip out first / from url that add by UrlHelper.
@Code ViewData("Title") = "Index" End Code <h2>Index</h2> LegacyUrl is: <b>@model.ToString </b> <p>Outgoing Legacy URL Generation</p> @Html.ActionLink("legacyLink","Index",New with {.legacyUrl="~/Content/StaticContent.htm"})
finally its time to define route that handle the legacy url.
routes.RouteExistingFiles = True routes.Add(New LegacyRoute("~/content/staticcontent.htm", "~/content/OtherStaticContent.htm"))
we enabled the disk file routing because here we testing route with url that point to disk file. but you can use same logic with url that point to particular action. we created new instance of our custom LegacyRoute and pass url array that is going to match with requested and our LegacyController will display it in view.
Today, I went to the beach with my children. I found a sea shell and gave it to my 4 year old
ReplyDeletedaughter and said "You can hear the ocean if you put this to your ear." She placed the shell to her ear and screamed.
There was a hermit crab inside and it pinched her ear. She never wants to go back!
LoL I know this is entirely off topic but I had to tell someone!
my weblog - volcanology