ASP. NET MVC URL rewrite and optimization (advanced)-Inherit routebase URL

Source: Internet
Author: User

Http://www.cnblogs.com/John-Connor/archive/2012/05/03/2478821.html

Introduction--

In the introductory chapter, we describe how to use the global file in an ASP. NET MVC-based Web program to simply rewrite the route. It also introduces its own limitations-depending on the key-value pairs in the routing information:

If a value is not in a key-value pair, we cannot use it to make up the URL expression we want.

Primary Portal: customizing URLs with the Global routing table

In the advanced chapter, we will introduce the base class of the ASP. NET route-related class-abstract class RouteBase, and show how to inherit it to make URL rewriting and optimization into free Style.

One, the needs of the boss

Suppose we are a mobile phone sales site of a program ape (to undertake the primary article), after the first URL rewrite, our Mobile phone category page URL changes:

Http://www.xxx.com/category/showcategory?categoryid=0001&view=list&orderby=price&page=1
=
http://www.xxx.com/category/0001

Now the boss has proposed new requirements, URL semantics, and thus better reflect the structure of the site:

Http://www.xxx.com/ca-categoryname

For example, Nokia is a classification, then the corresponding URL is/ca-nokia, if it is the iphone category, the URL corresponds to/ca-iphone. The CA prefix means classification category.

It is not possible to configure the global file for this simple requirement. Let's start by introducing the base class RouteBase for all the classes of ASP .


Second,Introduction and operation mechanism of RouteBase class

1. The RouteBase class is located in the System.Web.Routing namespace, with the following structure:

    Public abstract class RouteBase    {        protected routebase ();        Public abstract Routedata Getroutedata (HttpContextBase HttpContext);        Public abstract Virtualpathdata GetVirtualPath (RequestContext requestcontext, routevaluedictionary values);    }
    • Getroutedata: Returns an object based on the HTTP request information-contains the value of the route definition if the route matches the current request, or null if the route does not match the request.
    • GetVirtualPath: Checks if the route value matches a rule, returns an object that contains the generated URL and information about the route, or null if the route does not match values.
    • RouteBase: Initializes the class for use by inherited class instances. This constructor can only be called by an inherited class.

After reading the above definition, we may faint flowing away quickly. Let's get a simple example of how these methods work.

First we create a new class library johnconnor.routing, and inherit the abstract class RouteBase:

Using system;using system.collections.generic;using system.linq;using system.text;
Using system.web.mvc;//needs to add references, use version 3.0 with system.web.routing;using johnconnor.models;

namespace johnconnor.routing{public class Categoryurlprovider:routebase {public override Routedata Getroutedata (System.Web.HttpContextBase HttpContext) { return null;//breakpoint 1 } public override Virtualpathdata GetVirtualPath (RequestContext requestcontext, routevaluedictionary values) { return null;// Breakpoint 2}}}

This allows the Categoryurlprovider class to include methods for handling route mappings.

First we need to add a reference to the johnconnor.routing class Library in the Web program, and then we register the Categoryurlprovider class in the routing table of the global file.

    public static void RegisterRoutes (RouteCollection routes)        {
Routes. Ignoreroute ("{resource}.axd/{*pathinfo}"); Routes. ADD (New JohnConnor.Routing.CategoryUrlProvider ());//Classification rules
Routes. MapRoute ("Home", "" ", new {controller =" Home ", action =" Index "});//Home
}

This is the equivalent of adding a new routing rule. Regenerate the Web program to make a breakpoint in Categoryurlprovider, F5 start.

2. Getroutedata () method

At this time quite with you entered in the browser http//localhost:1234/< assumes that the local port number is 1234>, at which point the program needs to determine which route value this URL matches.

A top-down match will first attempt to match our new classification routing rule, which will hit the breakpoint in the Getroutedata () method.

Because we returned null, which means that the request does not match our new classification routing rule, the program will continue to match from top to bottom in the routing table.

Until this rule in the home page matches its URL expression, the corresponding route value is obtained-call the Homecontroller.index () method.


If you modify the Getroutedata () method:

public override Routedata Getroutedata (System.Web.HttpContextBase HttpContext)        {            var data = new Routedata (this , new Mvcroutehandler ());            Data. Values.add ("Controller", "Home");            Data. Values.add ("Action", "Index");            return data;        }

You will be directed to the Homecontroller.index () method whether you enter any relative URLs after http//localhost:1234/.

Because the route value is returned instead of NULL, it means that a match has been found and no further matching is made. < This rule overrides all the following rules >

Of course, please don't write like this ...

This allows you to infer the role that the Getroutedata () method plays in the route map: processing the URL in the request, returning the corresponding route value, or returning NULL if no processing or mismatch is found.

  3. Virtualpathdata () method

If you have a code in the Razor page that gets the URL by specifying a route value

<a href= "@Url. Action (" Index "," Home ")" > Home </a>

When the view engine renders the page to this code, the Homecontroller.index () method is parsed into a routevaluedictionary-type, case-insensitive key-value pair < Assuming that the key-value pair object is values>

values["Controller"]= "Home"; values["Action"]= "Index";

This key-value pair represents a route value.

It is also a top-down match for this route value in the routing table, and when the first classification rule is attempted, the breakpoint in the Virtualpathdata () method is hit.

We return a null, which indicates a mismatch, and the program makes a match for the next rule.

The corresponding relative URL "" is constructed, and the URL is returned, until the route value of the page rule is found to match.

Shown as:

<a href= "http://localhost:1234/" > Home </a>

If we also rewrite the Virtualpathdata () method:

  

public override Virtualpathdata GetVirtualPath (RequestContext requestcontext, routevaluedictionary values)        {            return  New Virtualpathdata (This, "This-is-a-test-url");        }

The result is that the URL you construct through the above method will appear as Http://localhost:1234/This-is-a-Test-URL regardless of where the request came from.

Because we are returning a relative path instead of NULL, indicating that a match has been found, the match does not go down. < This rule overrides all subsequent rules >

Again, please do not write this ...

It can be seen that Virtualpathdata () live in the route map: processing the request with the route key-value pair, generating the corresponding URL, not processing or mismatch returns NULL.

4. Rules for method overrides

  In the above, I repeatedly use the Red font hint, please do not write this. Because of the overriding class for each URL, it is recommended that you only handle as few route mappings as possible .

For example, Categoryurlprovider only handles the mapping of the Categorycontroller.show (string Categoeyid) action method. All mappings that are not related to this method return null.

Continue to match other rules.

Three, start the hand ~

  For the fastest explanation, we have simplified the content of the site. The following will help you understand the program, and if you have enough time, build a website yourself to try the following.

First we create Category.cs in the johnconnor.routing class library to save the classification model and save all the categories displayed in List<category>,

Using system;using system.collections.generic;using system.linq;using system.web;namespace JohnConnor.Models{    / /classification Model Public    class category    {public        string Categoeyid {get; set;}        public string Categoeyname {get; set;}    }    public static class Categorymanager    {        //Here only shows the creation of three classifications as an example, in practice allcategories can be read from the data source. Public        static readonly list<category> allcategories = new List<category>        {            new category () {categoeyid= "001", Categoeyname= "Nokia"},            new category () {categoeyid= "002", Categoeyname= "IPhone"},            new Category () {categoeyid= "003", Categoeyname= "Anycall"}        };}    }

Suppose the Categorycontroller of our website is like this.

Using system;using system.collections.generic;using system.linq;using system.web;using System.Web.Mvc;using Johnconnor.models;namespace johnconnor.web.controllers{public    class Categorycontroller:controller    {        Public ActionResult showcategory (string id)        {            var category = CategoryManager.AllCategories.Find (c + = c). Categoeyid = = ID);            Return View (category);}}    }

First we suggest that thevirtualpathdata () and Getroutedata () methods appear in pairs. Once you have established a routing rule, such as the classification rule/ca-categoryname, then:

    • Getroutedata () must process each URL that matches this rule, return the same route value , discard the URL that does not match, return null, and let the match continue.
    • Virtualpathdata () must handle each routing request that matches this rule , returning the same URL; Discard The mismatched request, return NULL, and let the match continue.

  !!! The two complement each other to complete the route value and URL mapping, missing one, it does not constitute a complete routing rules. The direct result is an error of 404 or a URL address generated.

Code for Getroutedata ():

public override Routedata Getroutedata (System.Web.HttpContextBase HttpContext) {var virtualpath = Httpc Ontext. Request.apprelativecurrentexecutionfilepath + httpcontext.request.pathinfo;//Get relative path
VirtualPath = virtualpath.substring (2). Trim ('/');//At this point the URL will be ~/ca-categoryname, intercept the back Ca-categoryname
if (!virtualpath.startswith ("ca-"))//Determine whether we need to process the URL, not return null, the match will continue. return null; var CategoryName = virtualpath.split ('-'). Last ();//intercept the category name after the ca-prefix
Try to get the classification according to the category name, ignoring the case var category = CategoryManager.AllCategories.Find (c = c.categoeyname.equals (category Name,stringcomparison.ordinalignorecase)); if (category = = null)//If the classification is NULL, it may not be the URL we want to process, return NULL, let the match continue to return null; At this point we have to deal with the URL of the var data = new Routedata (This, new Mvcroutehandler ());//Declare a routedata, add the corresponding route value D Ata. Values.add ("Controller", "Category"); Data. Values.add ("Action", "Showcategory"); Data. Values.add ("id", category.) Categoeyid); Return data;//returns this route value will call Categorycontroller.showcategory (category. Categoeyid) method. Match termination}

Code for Virtualpathdata ()

public override Virtualpathdata GetVirtualPath (RequestContext requestcontext, routevaluedictionary values) { Determine whether the request originated from Categorycontroller.showcategory (string id), not return null, let the match continue var categoryId = values["id"] as str            ing            if (categoryId = = null)//missing parameter ID in routing information, not the request we are processing, returns null return null; The request is not Categorycontroller initiated, not the request we are processing, and returns null if (!values. ContainsKey ("Controller") | | !values["Controller"]. ToString ().            Equals ("category", StringComparison.OrdinalIgnoreCase)) return null; The request was not initiated by the Categorycontroller.showcategory (string id), not the request we were processing, and the null if (!values) was returned. ContainsKey ("action") | | !values["Action"]. ToString ().            Equals ("Showcategory", stringcomparison.ordinalignorecase)) return null; At this point, we can determine that the request was categorycontroller.showcategory (string id), generate the corresponding URL and return var category = Categorymanager.allcateg Ories.      Find (c = C.categoeyid = = categoryId);      if (category = = null) throw new ArgumentNullException ("category");//Cannot find categorical throw exception var path = " ca-"+ category. Categoeyname.trim ();//Generate URL return new Virtualpathdata (this, path.        Tolowerinvariant ()); }

At this point, we have completed the mapping of this routing rule. If you have mastered the above technology, any URL rewriting and optimization requirements, I believe you can hold.

If our homepage page is such <razor view engine;:

@model list<johnconnor.models.category>@{    viewbag.title = "Home";} 

Three categorical connections you get this result.

<a href= "/ca-nokia" >nokia</a><a href= "/ca-iphone" >iphone</a><a href= "/ca-anycall" > Anycall</a>

Clicking on each connection will first go to our handler and generate the appropriate route value-Call the Categorycontroller.showcategory (string id) method to display the corresponding category page based on the ID.

------------------------------------------------------the end of the advanced article---------------------------------------------------

  

I spent a lot of time thinking about how to use a simple example of inheriting routebase for URL rewriting and optimization.

Hope to help people who are useful.

Need program source code friend point here: JohnConnor.UrlRewrite.rar

If you have any questions, please correct and discuss them.

  

ASP. NET MVC URL rewrite and optimization (advanced)-Inherit routebase URL

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.