This article focuses on how to bind a two-level domain name to a specific controller in ASP.
Application scenario: The Enterprise Portal site will be different depending on the content, set up different sections, such as Sina Sports, entertainment channels, and so on. In some cases, you need to set different two-level domain names for different plates, such as Sina Sports sports.sina.com.cn.
in ASP. NET core MVC, if you want to implement the effect of the plate, you may create different controllers for different plates (but there are other techniques, which do not discuss how the implementation is good or bad), in this case, how to bind the controller to a unique level two domain name, For example, the sports channel corresponding controller called Sportcontroller, through the sports. xxx.com domain access to the system, directly into the Sportcontroller, and through this level two domain name can not access other controllers.
The above said the scene, see below how to achieve.
There is a routing rule configuration in ASP. NET core MVC, where the configuration is in the Startup.configure method, the code is as follows:
App. USEMVC (Routes =>{ routes. MapRoute ( name: "Default", Template: "{controller=home}/{action=index}/{id?}", defaults:new {area= " Admin "});
Unfortunately, support for domain names is not supported (I now understand that if there is a problem, please correct me). Through routes. Maprouter registers the routing rules and joins the RouteCollection, and when a request comes in, routercollection loops through all the registered Irouter objects and finds the first matching irouter. Although the framework does not support the domain name configuration rules, but we can implement a irouter, in the implementation of the two-level domain name judgment logic, I here temporarily named Subdomainrouter, the specific implementation code as follows:
public class Subdomainrouter:routebase {private readonly irouter _target; Private readonly string _subdomain; Public Subdomainrouter (Irouter target, String subdomain,//the two-level domain name that is bound by the current routing rule string routetemplate, routevalued Ictionary defaults, RouteValueDictionary constrains, Iinlineconstraintresolver inlineconstraintresolver): Bas E (routetemplate, subdomain, inlineconstraintresolver, defaults, constrains, new Routeva Luedictionary (null)) {if (target = = null) {throw new ArgumentNullException (nameof (target)); } if (subdomain = = null) {throw new ArgumentNullException (nameof (subdomain)); } _subdomain = subdomain; _target = target; public override Task Routeasync (Routecontext context) {string domain = context. httpcontext.request.host.host;//gets the current request domain name, and then compares with _subdomain, ignoring if (string) if you don't want to wait. IsNullOrEmpty (domain) | | String.Compare (_subdomain, domain)! = 0) { return task.completedtask; }//If the domain name matches, then verify that the access path matches the return base. Routeasync (context); } protected override Task onroutematched (Routecontext context) {context. ROUTEDATA.ROUTERS.ADD (_target); Return _target. Routeasync (context); } protected override Virtualpathdata onvirtualpathgenerated (Virtualpathcontext context) {return _target. GetVirtualPath (context); } }
From the above code we only see the domain name detection, but how to direct the domain name to a specific controller, which requires us to register this irouter time to do some articles, directly on the code:
public static class Routebuilderextensions {public static Iroutebuilder Mapdomainroute (this iroutebuilder route Builder,string domain,string area,string Controller) {if (string. IsNullOrEmpty (area) | | String. IsNullOrEmpty (Controller)) {throw new ArgumentNullException ("area or controller can is not NULL"); } var inlineconstraintresolver = Routebuilder. ServiceProvider. Getrequiredservice<iinlineconstraintresolver> (); String template = ""; RouteValueDictionary defaults = new RouteValueDictionary (); RouteValueDictionary constrains = new RouteValueDictionary (); Constrains. ADD ("area", area); Defaults. ADD ("area", area); Constrains. ADD ("Controller", Controller); Defaults. ADD ("Controller", String. IsNullOrEmpty (Controller)? "Home": Controller); Defaults. ADD ("Action", "Index"); Template + = "{Action}/{id}"; The controller information is no longer included in the/path rule, but the controller name required for the lookup is limited by constrains ROUTEBUILDER.ROUTES.ADD (New Subdomainrouter (Routebuilder.defaulthandler, domain, template, defaults, constrains, INL Ineconstraintresolver)); return routebuilder; }}
Finally, we can register the corresponding rules in startup, as follows:
public static class Routebuilderextensions {public static Iroutebuilder Mapdomainroute (this iroutebuilder route Builder,string domain,string area,string Controller) {if (string. IsNullOrEmpty (area) | | String. IsNullOrEmpty (Controller)) {throw new ArgumentNullException ("area or controller can is not NULL"); } var inlineconstraintresolver = Routebuilder. ServiceProvider. Getrequiredservice<iinlineconstraintresolver> (); String template = ""; RouteValueDictionary defaults = new RouteValueDictionary (); RouteValueDictionary constrains = new RouteValueDictionary (); Constrains. ADD ("area", area); Defaults. ADD ("area", area); Constrains. ADD ("Controller", Controller); Defaults. ADD ("Controller", String. IsNullOrEmpty (Controller)? "Home": Controller); Defaults. ADD ("Action", "Index"); Template + = "{Action}/{id}"; The controller information is no longer included in the/path rule, but the controller name required for the lookup is limited by constrains ROUTEBUILDER.ROUTES.ADD (New Subdomainrouter (Routebuilder.defaulthandler, domain, template, defaults, constrains, INL Ineconstraintresolver)); return routebuilder; }}