PBMining

Searching...
Monday, June 11, 2012

Customizing Routing System in Asp.net MVC 3

3:44 AM

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.

Index.vbhtml
       @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.

1 comments:

  1. Today, I went to the beach with my children. I found a sea shell and gave it to my 4 year old
    daughter 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

    ReplyDelete

Write your review about this post.