先分析需求 在MVC項目中,我們如果有兩個Areas。比如Test和DEMO。我們的訪問地址應該是 http://localhost:8098/test http://localhost:8098/demo 如果我們綁定功能變數名稱後想實現這樣訪問 http://test.abc.com:8098/ htt ...
先分析需求
在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; } }View Code
DomainRouteTable類裡面有一個靜態屬性DomainRoutes。主要存儲功能變數名稱和路由之間的存儲關聯。

public class DomainRouteTable { private static Dictionary<string, RouteCollection> _instance = new Dictionary<string, RouteCollection>(); public static Dictionary<string, RouteCollection> DomainRoutes { get { return _instance; } } }View Code
下麵就是重寫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; } }View Code
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; } }View Code
接下來在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" });View Code
代碼看起來是這樣的,這樣並不影響之前的訪問,還是可以通過areas的方式訪問的
同理demo區域也添加代碼。
接著編譯我們的項目,就可以用demo.abc.com:8098來訪問了,是不是很簡單。
訪問後的效果
本文參考文章地址
https://www.cnblogs.com/hitearth/p/6848788.html