004_URL route, 004_url route

Source: Internet
Author: User
Tags actionlink

004_URL route, 004_url route
Custom Routing System

The routing system is flexible and configurable. You can also use the following two methods to customize the routing system to meet other requirements.

1. Create a custom RouteBase;

2. Create a custom route handler.

Create a custom RouteBase implementation

To create a custom RouteBase implementation, You need to implement a RouteBase derived class, which requires the following two methods:

  • GetRouteData (HttpContextBase httpContext): This is the working mechanism for inbound URL matching. The Framework calls this method for each entry of RouteTable. Routes in sequence until one of them returns a non-null value.
  • GetVirtualPath (RequestContext requestContext, RouteValueDictionary values): this mechanism is used to generate outbound URLs. The Framework calls this method for each entry of RouteTable. Routes in sequence until one of them returns a non-null value.

To demonstrate this custom method, a RouteBase derived class is created here. Let's assume that we need to migrate an existing application to the MVC framework, but for whatever reason, we need to be compatible with the previous URL, that can be done in this way. Of course, you can use the routing system of the rule to handle it. This method is not discussed here.

First, create a controller to process old-style routing requests and name it "LegacyController", for example:

Using System. web. mvc; namespace UrlsAndRoutes. controllers {// <summary> // Controller used to process legacy URL requests /// </summary> public class LegacyController: Controller {public ActionResult GetLegacyURL (string legacyURL) {// before the application is migrated to MVC, the request is for the file. Therefore, the requested file must be processed here. However, here // only briefly describes the implementation principle of the custom RouteBase. Therefore, this URL is only displayed in the view. Return View (object) legacyURL );}}}

The code above converts the parameters in the View method. If no conversion is performed, then the C # compiler mistakenly believes that the parameter should be used as the string of the name of the View to be rendered (the implementation of an overloaded version of the View method ). The following is the view of this action method GetLegacyURL. cshtml:

@model string@{    ViewBag.Title = "GetLegacyURL";    Layout = null;}

 

1, For the input URLRoute

Create a LegacyRoute class in the Infrastructure folder. Its content is as follows:

using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Mvc;using System.Web.Routing;namespace UrlsAndRoutes.Infrastructure{    public class LegacyRoute : RouteBase    {        private string[] urls;        public LegacyRoute(params string[] targetUrls)        {        }        public override RouteData GetRouteData(HttpContextBase httpContext)        {            RouteData result = null;            string requestedURL = httpContext.Request.AppRelativeCurrentExecutionFilePath;            if (urls.Contains(requestedURL, StringComparer.OrdinalIgnoreCase))            {                result = new RouteData(this, new MvcRouteHandler());                result.Values.Add("controller", "Legacy");                result.Values.Add("action", "GetLegacyURL");                result.Values.Add("legacyURL", "requestedURL");            }            return result;        }        public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)        {            return null;        }    }}

Register a route so that it uses the new RouteBase derived class:

Public static void RegisterRoutes (RouteCollection routes) {// register a custom RouteBase to implement routes. Add (new LegacyRoute ("~ /Articles/windows_3.20.overview.html ","~ /Old/. NET_1.0_Class_Library "));}

2Generate output URL

Implement the GetVirtualPath method in LegacyRoute to support generating output URLs. For example:

Public override VirtualPathData GetVirtualPath (RequestContext requestContext, RouteValueDictionary values) {VirtualPathData result = null; if (values. containsKey ("legactURL") & urls. contains (string) values ["legacyURL"], StringComparer. ordinalIgnoreCase) {// If a match exists, a VirtualPathData object will be created, and a reference to the current object and an outbound URL will be passed in it. Because the routing system has already attached the // character "/" to this URL in advance, the leading character must be deleted from the generated URL. Result = new VirtualPathData (this, new UrlHelper (requestContext). Content (string) values ["legacyURL"]). Substring (1);} return null ;}

Add the following code to the ActionName. cshtml view to generate an output URL for the custom ro:

<Div> @ * generate an output URL through custom routing * @ This is a URL: @ Html. ActionLink ("Click me", "GetLegacyURL", new {legacyURL = "~ /Articles/windows_3.20.overview.html "}) </div>

The above code will generate such a element:

<A href = "/articles/windows_3.20.overview.html"> Click me </a>

The anonymous type created with the legacyURL attribute is converted to the RouteValueDictionary class containing the same name key.

Create a custom route Handler

The route already depends on this MvcRouteHandler, because MvcRouteHandler connects the routing system to the MVC framework. However, by implementing the IRouteHandler interface, the routing system still allows you to customize your own route handler, as shown in the following example:

using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Routing;namespace UrlsAndRoutes.Infrastructure{    public class CustomRouteHandler : IRouteHandler    {        public IHttpHandler GetHttpHandler(RequestContext requestContext)        {            return new CustomHttpHandler();        }    }    public class CustomHttpHandler : IHttpHandler    {        public bool IsReusable        {            get { return false; }        }        public void ProcessRequest(HttpContext context)        {            context.Response.Write("Hello");        }    }}

The purpose of the IRouteHandler interface is to provide the Implementation of The IHttpHandler interface, which is responsible for processing the request. In the MVC implementation of this interface, it is mainly responsible for these tasks: Finding controllers, calling action methods, rendering views, and writing the results into the response. Of course, the implementation here is much simpler. Here, only the word "Hello" is written to the client and only in the text format. To get the final result, you must register the Custom Handler in the RouteConfig. cs file:

Public static void RegisterRoutes (RouteCollection routes) {// register the custom Route handler routes. Add (new Route ("SayHello", new CustomRouteHandler ()));}

 

Region

The MVC framework allows you to organize Web applications into areas. Each Area represents a functional end of an application, such as management, settlement, and customer support. This makes code management very useful, especially for large projects. If you only use a group of folders for All controllers, views, and models, it will be very difficult to manage.

Create Region

You can right-click the project and choose "add"> "region" to add the project. You can also create other regions in the current region. After the preceding operation, the following regional folder structure will appear in the project:

The Areas/Admin folder shows that this is a small MVC project. There are "Controllers", "Models", and "Views" folders. The first two are empty, but the "Views" folder contains a "Shared" folder and a Web. config view engine configuration file (view engine is not discussed here ).

In addition, an AdminAreaRegistration. cs file is added, such:

using System.Web.Mvc;namespace UrlsAndRoutes.Areas.Admin{    public class AdminAreaRegistration : AreaRegistration    {        public override string AreaName        {            get            {                return "Admin";            }        }        public override void RegisterArea(AreaRegistrationContext context)        {            context.MapRoute(                "Admin_default",                "Admin/{controller}/{action}/{id}",                new { action = "Index", id = UrlParameter.Optional }            );        }    }}

 

From the list, we can see that the RegisterArea method in this class registers a route in the URL mode Admin/{controller}/{action}/{id. Of course, you can also define other routes dedicated to the region in this method.

Note: To assign a route name, make sure that these names are unique throughout the application, not just in a region.

Because the registration of routes has been processed in the Application_Start method of Global. asax, you do not need to take other measures during the development process to ensure that the registration method will be called:

    public class MvcApplication : System.Web.HttpApplication    {        protected void Application_Start()        {            AreaRegistration.RegisterAllAreas();            WebApiConfig.Register(GlobalConfiguration.Configuration);            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);            RouteConfig.RegisterRoutes(RouteTable.Routes);            BundleConfig.RegisterBundles(BundleTable.Bundles);        }    }

The static method AreaRegistration in the above Code. by calling RegisterAllAreas, the MVC Framework traverses all classes of the application, finds all classes derived from AreaRegistration, and calls the RegisterArea Method on these classes.

Note: you do not need to modify the route-related statement sequence in Application_Start. If you call RegisterRoutes before AreaRegistration. RegisterAllAreas, the route is defined before the region route. Because the routing system is evaluated in order, this means that requests to the Regional Controller may be matched using incorrect routes.

Note: The MapRoute method in the AreaRegistrationContext class automatically limits the registered route to the namespace containing the region controller. That is to say, when a controller is created in a region, it must be placed in its default namespace; otherwise, it cannot be found by the routing system.

Filling Area

In the previous section "Create a region", you know that you can create controllers, views, and models in a region. Next, we will create a controller class named HomeController to demonstrate the separation between zones in the application:

Right-click the Controllers folder in to add an empty Controller: HomeController

 

using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Mvc;namespace UrlsAndRoutes.Areas.Admin.Controllers{    public class HomeController : Controller    {        public ActionResult Index()        {            return View();        }    }}

For demonstration, right-click the Index Action Method in the Controller and add the corresponding View. The added View is in the Areas/Admin/View/Home path.

 

The View content is as follows:

@{    ViewBag.Title = "Index";    Layout = null;}<!DOCTYPE html>

From the above introduction, we can see that the working method in a region is quite similar to that in the main area of an MVC project. The workflow for creating an item in a project is the same. The effect is as follows (navigation path: Admin/Home/Index ):

 

Unclear controller resolution

Areas may not be self-contained as they are displayed. When a region is registered, any route defined is restricted to the namespace associated with the region. This is also the reason why I can request/Admin/Home/Index and obtain the HomeController class in the WorkingWithAreas. Admin. Controllers namespace.

However, the routes defined in the RouteConfig. cs RegisterRoutes method are not subject to similar restrictions. As a reminder, the routing configuration for the sample application is given here:

        public static void RegisterRoutes(RouteCollection routes)        {             routes.Add(new Route("SayHello", new CustomRouteHandler()));            routes.Add(new LegacyRoute("~/articles/Windows_3.1_Overview.html", "~/old/.NET_1.0_Class_Library"));            routes.MapRoute("MyRoute", "{controller}/{action}");            routes.MapRoute("MyOtherRoute", "App/{action}", new { controller = "Home" });        }

The Route named "MyRoute" converts the input URL from the browser to the Index action on the Home controller. At this time, an error message will be received. Because there is no namespace constraint set for this route, the MVC Framework will see two HomeController classes. To solve this problem, you need to prioritize the primary controller namespace in all routes that may cause conflicts, such:

        public static void RegisterRoutes(RouteCollection routes)        {             routes.Add(new Route("SayHello", new CustomRouteHandler()));            routes.Add(new LegacyRoute("~/articles/Windows_3.1_Overview.html", "~/old/.NET_1.0_Class_Library"));            routes.MapRoute("MyRoute", "{controller}/{action}",null,new[] {“UrlsAndRoutes.Controllers”});            routes.MapRoute("MyOtherRoute", "App/{action}", new { controller = "Home" }, new[] {“UrlsAndRoutes.Controllers”});        }

The bold Section in the code above takes the project controller as a priority. Of course, you can also give priority to controllers in a region.

Generate links to regional actions

You do not need to take special steps to create links to actions in the same region. The MVC Framework detects the specific regions involved in the current request, and then the outbound URL is generated to find a match in the routes defined in the region. For example, add the following code to the view in the Admin region.

@Html.ActionLink("Click me", "About")

The following HTML is generated:

<A href = "/Admin/Home/About"> Click me </a>

To create a link for actions in different regions or actions without a region, you must create a variable named "area" and use it to specify the region name, for example:

@Html.ActionLink("Click me to go to another area", "Index", new { area = "Support" })

Therefore, area is reserved as the variable name of the fragment. Assume that a region named Support has been created and the corresponding standard routing definition is available, the following HTML is generated:

<A href = "/Support/Home"> Click me to go to another area </a>

If you want to link to an action on the top-level controller (a controller in the/Controllers folder), you should specify the area as an empty string, such:

@ Html. ActionLink ("Click me to go to another area", "Index", new {Area =""})

URL scheme Best Practices

1. Make the URL clean and user-friendly

Below are some simple outlines for generating friendly urls:

  • Design URLs to describe their content, rather than the implementation details of the application. Use/Articles/AnnualReport instead of/Website_v2/CachedContentServer/FromCache/AnnualReport.
  • Try to use the content title rather than the ID. Use/Articles/AnnualReport instead of/Articles/2392. If you must use an ID (to distinguish an entry with the same title or to avoid unnecessary database query steps when searching for an entry using the title), both of them (for example: /Articles/2392/AnnualReport ). This requires more characters, but more significance, and will improve the search engine arrangement.
  • ). If mime is set properly, the webbrowser will not extend the name of the target file, but they hope to use the extension for the target file.
  • Create a sense of attention (such as/Products/Menswear/Shirts/Red), so that you can easily guess the URL of the parent directory.
  • Case Insensitive. The ASP. NET routing system is case insensitive by default.
  • Avoid matching, code, and character sequence. You can use a short horizontal line (for example,/my-great-article) when you need to use a word separator ). Underlines are unfriendly, while URL-encoded spaces are odd (/my + great + article) or annoying (/my % 20 great % 20 article ).
  • You do not need to modify the URL. Breaking the Link means losing business. When you do need to modify the URL, you can continue to support the old URL scheme for as long as possible through permanent redirection (301.
  • Consistent. Use a URL format throughout the application. URLs should be short, easy to input, editable (user-friendly and stable), and they should visualize the website structure.

2. GET and POST: select the correct one.

In general, GET requests should be used for retrieval of all read-only information, and POST requests should be used for various operations to modify the application status. In standard terms, GET requests are used for secure interaction (except information retrieval), while POST requests are used for insecure interaction (making decisions or modifying something ). A GET request is an address that can be set-all information is contained in a URL, so it can be set as a bookmarkdonet and linked to these addresses. (These conventions are set by the global Internet Alliance (W3C) at http://www.w3.org/products/rfc2616/rfc2616-sec9.html)

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.