Learning ASP. NET MVC5 framework secrets-How ASP. net mvc runs (2)

Source: Internet
Author: User

Learning ASP. NET MVC5 framework secrets-How ASP. net mvc runs (2)
Routing

For an ASP. for the net mvc application, HTTP request processing is implemented in an Action of the Target Controller type. Each HTTP request is not like ASP. NET Web Forms applications are also for a physical file, but for an Action method of a Controller. The name of the target Controller and Action is determined by the URL of the HTTP request. net mvc receives the incoming request. The first task is to parse the current HTTP request to obtain the name of the target Controller and Action. This process is implemented through ASP. net mvc routing system. We constructed a simple routing system using the following objects.

1. RouteData

ASP. NET defines a global Route table. Each Route object in the Route table contains a routing template. The name of the target Controller and Action can be defined in the template as a placeholder through the routing variable, or it can be used as the default value of the routing object (no need to appear in the routing template ). For each HTTP request, the routing system traverses the Route table and finds a Route object that matches the current request URL pattern, then, it is used to parse the route data with the Controller and Action name as the core. In our self-built ASP. net mvc Framework, the route data obtained through route Parsing is represented by the RouteData type defined below.

 

public class RouteData    {        public IDictionary
 
   Values { get; private set; }        public IDictionary
  
    DataTokens { get; private set; }        public IRouteHandler RouteHandler { get; set; }        public RouteBase Route { get; set; }         public RouteData()        {            this.Values = new Dictionary
   
    ();            this.DataTokens = new Dictionary
    
     ();            this.DataTokens.Add(namespaces, new List
     
      ());        }         public string Controller        {            get            {                object controllerName = string.Empty;                this.Values.TryGetValue(controller, out controllerName);                return controllerName.ToString();            }        }         public string ActionName        {            get            {                object actionName = string.Empty;                this.Values.TryGetValue(action, out actionName);                return actionName.ToString();            }        }    }
     
    
   
  
 

 

RouteData defines two dictionary-type attributes: Values and DataTokens. They represent routing variables with different sources. The former is obtained by performing route Resolution on the request URL. The attributes of the Controller and Action names are extracted directly from the Values attribute dictionary. The corresponding keys are "controller" and "action", respectively ".

ASP. net mvc is implemented by the custom HttpModule and HttpHandler components. HttpModule is obtained from the RouteHandler attribute of the RouteData object. The RouteHandler attribute type of RouteData is the IRouteHandler interface, which has a unique GetHttpHandler method to return the HttpHandler object that truly processes HTTP requests. This method has a parameter of the RequestContext type. RequestContext indicates the context of the current (HTTP) request. Its core is the encapsulation of the current HttpContext and RouteData.

 

public interface IRouteHandler    {        IHttpHandler GetHttpHandler(RequestContext requestContext);    }public class RequestContext    {        public virtual HttpContextBase HttpContext { get; set; }        public virtual RouteData RouteData { get; set; }    }


 

2. Route and RouteTable

The RouteData object that carries the Route variable is generated by the Route object that matches the current request in the Route table. You can obtain this Route object through the Route attribute of RouteData. The type of this property is RouteBase. As shown in the following code snippet, RouteBase is an abstract class that only contains a GetRouteData method with the return type RouteData.

 

public abstract class RouteBase    {        public abstract RouteData GetRouteData(HttpContextBase httpContext);    }

 

The GetRouteData method of RouteBase has a parameter of the type HttpContextBase, which represents the HTTP context of the current request. When this method is executed, it determines whether its defined routing rules match the current request, and implements route resolution when the matching succeeds, encapsulate the obtained route variables into RouteData objects and return them. If the routing rule does not match the current request, this method returns Null directly.

We have defined the next Route type inherited from RouteBase to complete specific routing work. A Route object has a Url attribute that represents the string type of the routing template. In the implemented GetRouteData method, we use HttpContextBase to obtain the URL of the current request. If it matches the pattern of the routing template, A RouteData object is created as the return value. For the returned RouteData object, its Values attribute indicates that the dictionary contains variables directly parsed from the object. For the DataTokens dictionary and RouteHandler attributes, the returned RouteData object is directly taken from the same name attribute of the Route object.

 

 public class Route : RouteBase    {        public IRouteHandler RouteHandler { get; set; }        public string Url { get; set; }        public IDictionary
 
   DataTokens { get; set; }         public Route()        {            this.DataTokens = new Dictionary
  
   ();            this.RouteHandler = new MvcRouteHandler();        }         public override RouteData GetRouteData(HttpContextBase httpContext)        {            IDictionary
   
     variables;            if (this.Match(httpContext.Request                 .AppRelativeCurrentExecutionFilePath.Substring(2), out variables))            {                RouteData routeData = new RouteData();                foreach (var item in variables)                {                    routeData.Values.Add(item.Key, item.Value);                }                foreach (var item in DataTokens)                {                    routeData.DataTokens.Add(item.Key, item.Value);                }                routeData.RouteHandler = this.RouteHandler;                return routeData;            }            return null;        }         protected bool Match(string requestUrl,out IDictionary
    
      variables)        {            variables = new Dictionary
     
      ();            string[] strArray1 = requestUrl.Split('/');            string[] strArray2 = this.Url.Split('/');            if (strArray1.Length != strArray2.Length)            {                return false;            }            for (int i = 0; i < strArray2.Length; i++)            {                if (strArray2[i].StartsWith({) && strArray2[i].EndsWith(}))                {                     variables.Add(strArray2[i].Trim({}.ToCharArray()), strArray1[i]);                }            }            return true;        }    }
     
    
   
  
 

A Web application can use multiple URL modes. Therefore, you must register multiple Route objects inherited from RouteBase. Multiple Route objects constitute a Route table. In our custom mini ASP. net mvc Framework, the route table is represented by the RouteTable type. RouteTable only has a Routes attribute of the RouteDictionary type, which indicates the global route table for the entire Web application.

 

 public class RouteTable    {        public static RouteDictionary Routes { get; private set; }        static RouteTable()        {            Routes = new RouteDictionary();        }    }


 

RouteDictionary indicates a list of named Route objects. We directly let it inherit from the generic Dictionary type Dictionary. The Key indicates the Registration Name of the Route object. In the GetRouteData method, we traverse the set to find the Route object matched by the specified HttpContextBase object and obtain the corresponding RouteData.

 

public class RouteDictionary : Dictionary
 
      {        public RouteData GetRouteData(HttpContextBase httpContext)        {            foreach (var route in this.Values)            {                RouteData routeData = route.GetRouteData(httpContext);                if (null != routeData)                {                    return routeData;                }            }            return null;        }    }
 

 

In Global. asax, we create a Route object based on the specified routing template and add it to the Global routing table represented by Routes, the static read-only attribute of RouteTable.

 

public class Global : System.Web.HttpApplication    {        protected void Application_Start(object sender, EventArgs e)        {            RouteTable.Routes.Add(default, new Route { Url = {controller}/{action} });        }    }


 

3. UrlRoutingModule

The role of a route table is to resolve the current HTTP request, and then obtain a route data with the Controller and Action name as the core, that is, the RouteData object described above. The whole routing Parsing is completed through a custom IHttpModule of the UrlRoutingModule type.

 

public class UrlRoutingModule : IHttpModule    {        public void Dispose()        { }         public void Init(HttpApplication context)        {            context.PostResolveRequestCache += OnPostResolveRequestCache;        }        protected virtual void OnPostResolveRequestCache(object sender, EventArgs e)        {            HttpContextWrapper httpContext = new HttpContextWrapper(HttpContext.Current);            RouteData routeData = RouteTable.Routes.GetRouteData(httpContext);            if (null == routeData)            {                return;            }            RequestContext requestContext = new RequestContext            {                RouteData = routeData,                HttpContext = httpContext            };            IHttpHandler handler = routeData.RouteHandler.GetHttpHandler(requestContext);            httpContext.RemapHandler(handler);        }    }


 

In the implemented Init method, we registered the PostResolveRequestCache event of HttpApplication. After the PostResolveRequestCache event that represents the current application's HttpApplication object is triggered, the UrlRoutingModule obtains the RouteDictionary object representing the global route table through the static read-only attribute Routes of RouteTable, create an HttpContextWrapper object based on the current HTTP context (HttpContextWrapper is a subclass of HttpContextBase) and call the GetRouteData method of the RouteDictionary object as a parameter.

If a method call returns a specific RouteData object, UrlRoutingModule creates a RequestContext object that represents the current context based on the object itself and the previously obtained HttpContextWrapper object, and pass it as a parameter to the GetHttpHandler method of RouteHandler of RouteData to get an HttpHandler object. UrlRoutingModule finally calls the RemapHandler method of the HttpContextWrapper object to map the obtained HttpHandler object. Then, the HttpHandler will take over the subsequent processing of the current HTTP request.

 

Related Article

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.