Custom Routing System
Through the previous study, we can feel the flexibility and configurability of the routing system. If these cannot meet our needs, we can customize the behavior. Next we will introduce how to customize the routing.
Create a custom implementation for the routebase class
If we do not like the URL matching method of the standard route object, or want to implement something special. We can derive a class from routebase to replace it. The derived classes allow us to control URL matching, parameter extraction, and creation of outgoing URLs. The following two methods must be implemented for the derived class:
1. getroutedata (httpcontextbase httpcontext): implements the matching mechanism of the incoming URL.
When every routetable. routes enters, the MVC Framework will call this method in turn until one of the calls returns a non-null value.
2. getvirtualpath (requestcontext, routevaluedictionary values): creates an outgoing URL.
When every routetable. routes enters, the MVC Framework will call this method in turn until one of the calls returns a non-null value.
The following is an example. Suppose we want to migrate a program to MVC, but some users have saved the program Link bookmarks or hardcoded them in the script. We still need to support the original URL. We can use the conventional routing system to handle this situation. Here we use this example to describe the custom route.
Create a legacycontroller with the following code:
View code
public ActionResult GetLegacyURL(string legacyURL)
{
return View((object)legacyURL);
}
In this simple controller, the getlegacyurl action method obtains a parameter and passes the parameter to view. If we really want to implement this controller, we need to use this method to retrieve the requested file. However, for simplicity, we only need to display the requested URL in the view.Note:Here we perform object type conversion for the parameters in the view. The reason is that the view () method itself has a string parameter overload. If we do not convert it here, the view will regard the string parameter as the name of a view, obviously, we do not want to jump to a view, but simply display it on the default view. :
After being converted to an object, the default view is used for rendering as the model. Add the getlegacyurl. cshtml view. The Code is as follows:
View code
@model string
@{
ViewBag.Title = "GetLegacyURL";
}
The URL requested was:@Model
As we have already implemented the derivation from routebase, next we will create a class legacyroute, as shown below:
View code
namespace UrlsAndRoutes.Infrastructure
{
public class LegacyRoute : RouteBase
{
private string[] urls;
public LegacyRoute(params string[] targetUrls)
{
urls = 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)
{
VirtualPathData result = null;
if (values.ContainsKey("legacyURL") && urls.Contains((string)values["legacyURL"], StringComparer.OrdinalIgnoreCase))
{
result = new VirtualPathData(this, new UrlHelper(requestContext).Content((string)values["legacyURL"]).Substring(1));
}
return result;
}
}
}
The constructor of this class needs to input a string array as the parameter, which shows the URLs supported by this routing class. The part defined in the getroutedata method is the routing system call to check whether it can process the incoming URL. If the request cannot be processed, null is returned, and the routing system will move to the next route to repeat the process. If the request can be processed, you need to return an instance that contains the controller and action variables and any other routedata class that you want to pass to the action method.
When we create a routedata object, we need to pass in the handler of the value to be processed. Here I use the mvcroutehandler class, such as: Result = new routedata (this, new mvcroutehandler ());
For the vast majority of MVC applications, this is the class we need, because it connects the routing system with the Controller/action model of an MVC program. Of course, we can also implement a class that replaces mvcroutehandler, that is, the custom route handler will be created later.
In the above routing implementation, we will route any request URL sent to the constructor. When getting such a URL, we add the hard-coded values of controller and action to the routevalues object, and we will also pass the requested URL as the legacyurl attribute, note that the attribute name must match the parameter name of the Action method to ensure that the created value can be passed to the action method through parameters. The last step is to register a new route derived from routebase. For example, routes. Add (New legacyroute ("~ /Article/windows_3.20.overview.html ","~ /Old/. net_1.0_class_library "); we created a legacyroute class instance, passed in the URL we want to route, and then added it to the routecollection using the add method. When we request a URL, it will be routed to our defined controller, as shown in:
Create outgoing URL
To support the creation of outgoing URLs, we need to implement the getvirtualpath method. Once again, if we cannot process a request, we will let the routing system know by returning a null value; otherwise, we will return an instance of the virtualpathdata class.
The Code is as follows:
View code
public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
VirtualPathData result = null;
if (values.ContainsKey("legacyURL") && urls.Contains((string)values["legacyURL"], StringComparer.OrdinalIgnoreCase))
{
result = new VirtualPathData(this, new UrlHelper(requestContext).Content((string)values["legacyURL"]).Substring(1));
}
return result;
}
The anonymous type is often used when passing segment variables or other detailed values, but here, the routing system converts these to routevaluedictionary objects. So we add a link in the view like this,
As follows:
View code
@Html.ActionLink("Click me", "GetLegacyURL", new { legacyURL =
"~/articles/Windows_3.1_Overview.html" })
The created anonymous type with the legacyurl attribute is converted into a routevaluedictionary object and contains a key with the same name.
In this example, if there is a key named legacyurl and its value is one of the URLs in the constructor of the legacyroute class we passed in, we decided to be able to process outgoing URL requests.
Create a custom route handler (route handler)
As mentioned above, our routes depend on the mvcroutehandler class because it is linked to the routing system and the MVC framework. We can customize route handle1r by implementing the iroutehandler interface, as shown below:
View code
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 iroutehandler interface aims to provide a way to create an implementation for the ihttphandler interface. The ihttphandler interface is responsible for processing requests. In the MVC implementation of these interfaces, the Controller will be found, the action method is called and the view is displayed. The result is written to response. The implementation in the instance is very simple, just write a "hello" to the client.
The following describes how to register a custom route:
Routes. add (new route ("sayhello", new customroutehandler (); then run the program and enter: http: // localhost: 57400/sayhello. The page displays "hello ".
Well, today's notes are here. The notes below are about areas and some best practices on URL architecture.
Good night!