asp.net MVC把Areas区域绑定成二级域名
先分析需求
在mvc项目中,我们如果有两个areas。比如test和demo。我们的访问地址应该是
http://localhost:8098/test
http://localhost:8098/demo
如果我们绑定域名后想实现这样访问
http://test.abc.com:8098/
http://demo.abc.com:8098/
这个问题的相关解决办法倒是不少,比如http://www.cnblogs.com/jobily/archive/2011/10/09/2204800.html。可惜都是破坏了原来项目的结构,对于已经上线的项目不太适用。
本文的解决办法实在不破坏原来的结构之上,在原来的areas里面重新绑定新的路由规则,重写基类路由 routebase的getroutedata方法达到绑定二级域名,访问areas的方法。
前期准备工作你需要先修改本地host文件,绑定一些二级域名。比如
127.0.0.1 demo.abc.com
127.0.0.1 test.abc.com
首先新建 areadomainregistrationcontext类。
public class areadomainregistrationcontext { /// <summary> /// /// </summary> /// <param name="_domainname">子域名 如:www.xxx.com 可以传 abc</param> public areadomainregistrationcontext(arearegistrationcontext _context, string _domainname) { domainname = _domainname; context = _context; } private string domainname; private arearegistrationcontext context; private routecollection routes { get { if (!domainroutetable.domainroutes.containskey(domainname)) { domainroutetable.domainroutes[domainname] = new routecollection(); } return domainroutetable.domainroutes[domainname]; } } public route maproute(string name, string url, object defaults, object constraints = null, string[] namespaces = null) { if (namespaces == null && context.namespaces != null) { namespaces = context.namespaces.toarray(); } route route = routes.maproute(name, url, defaults, constraints, namespaces); route.datatokens["area"] = context.areaname; route.datatokens["usenamespacefallback"] = false; route.datatokens["subdomain"] = domainname; return route; } }
domainroutetable类里面有一个静态属性domainroutes。主要存储域名和路由之间的存储关联。
public class domainroutetable { private static dictionary<string, routecollection> _instance = new dictionary<string, routecollection>(); public static dictionary<string, routecollection> domainroutes { get { return _instance; } } }
下面就是重写routebase的类了
public class domainroute : routebase { public resolvedomainname resolvedomainname = dependencyresolver.current.getservice<resolvedomainname>(); public routedata d = new routedata(null, new stoproutinghandler()); public override routedata getroutedata(httpcontextbase httpcontext) { string domainname = resolvedomainname.resolve(httpcontext); //该主机头没有配置,返回 null 继续查找路由 if (domainname == null) return null; if (!domainroutetable.domainroutes.containskey(domainname)) return d; var rs = domainroutetable.domainroutes[domainname]; routedata routedata = rs.getroutedata(httpcontext); if (routedata == null) return d; return routedata; } public override virtualpathdata getvirtualpath(requestcontext requestcontext, routevaluedictionary values) { string domainname = resolvedomainname.resolve(requestcontext.httpcontext); if (domainname == null) return null; if (!domainroutetable.domainroutes.containskey(domainname)) return null; var rs = domainroutetable.domainroutes[domainname]; virtualpathdata vpd = rs.getvirtualpathforarea(requestcontext, values); return vpd; } }
resolvedomainname主要映射areas和域名之间的关系,可以根据areas查找到域名。
public class resolvedomainname { public static dictionary<string, string> domainmap = new dictionary<string, string>(stringcomparer.ordinalignorecase); public string resolve(httpcontextbase httpcontext) { string key = httpcontext.request.headers["host"]; string value; if (domainmap.trygetvalue(key, out value)) { return value; } else return null; } }
接下来在global文件的里面的application_start方法里面的第一行加入一下代码
routetable.routes.add(new domainroute());
resolvedomainname.domainmap.add("demo.abc.com:8098", "demo1");
resolvedomainname.domainmap.add("test.abc.com:8098", "test");
这样就可以绑定多个域名,后面的demo1和test可以不和areas的名称相等,这里这是一个key而已。
接着在areas区域里面绑定路由的地方加入一下代码
var context2 = new areadomainregistrationcontext(context, "test"); context2.maproute( name: "test_default", url: "{controller}/{action}", defaults: new { controller = "home", action = "index" }, namespaces: new string[] { "webapplication1.areas.test.controllers" });
代码看起来是这样的,这样并不影响之前的访问,还是可以通过areas的方式访问的
同理demo区域也添加代码。
接着编译我们的项目,就可以用demo.abc.com:8098来访问了,是不是很简单。
访问后的效果
本文参考文章地址
https://www.cnblogs.com/hitearth/p/6848788.html
下一篇: python 自学之路-Day one