Because of the company's work arrangements, has been studying other technologies, so there is no time to update the blog, today can finally stop the things at hand, write some new content.
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 implementation code is 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 Routetemplat E, routevaluedictionary defaults, RouteValueDictionary constrains, iinlineconstraintresolver Inlineconstraintresolver): Base (Routetemplate, subdomain, inlineconstraintre Solver, defaults, constrains, new routevaluedictionary (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 (routecontextContext) {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 irouteb Uilder routebuilder,string domain,string area,string Controller) {if (string. IsNullOrEmpty (area) | | String. IsNullOrEmpty (Controller)) {throw new ArgumentNullException ("area or controller can" is 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/path rule no longer contains controller information, but the above constrains limits the controller name ROUTEBUILDER.ROUTES.ADD (new Subdomainrouter (Routebuilde R.defaulthandler, domain, template, defaults, constrains, inlineconstraintresolver); return routebuilder; }}
Finally, we can register the corresponding rules in startup, as follows:
App. USEMVC ( routes = { routes. Mapdomainroute ("xxx.domain.com", "AreaName", "controllername"); Routes. MapRoute ( name: "Default", Template: "{controller=home}/{action=index}/{id}", defaults:new {area = " Web "}); });
The implementation method may not be the best, but has met the basic needs, if you have a better way, welcome to discuss the exchange.