环境说明
项目采用mvc4,有个area,名称为 demo,访问路径 http://localhost:8098/demo,需要把demo.abc.com 映射到该路径
hosts 配置
127.0.0.1 demo.abc.com
核心代码
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;
}
}
public class DomainRouteTable
{
private static Dictionary<string, RouteCollection> _instance = new Dictionary<string, RouteCollection>();
public static Dictionary<string, RouteCollection> DomainRoutes
{
get
{
return _instance;
}
}
}
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;
}
}
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.asax.cs 的 Application_Start 放在最前面
RouteTable.Routes.Add(new DomainRoute());
ResolveDomainName.DomainMap.Add("demo.abc.com:8098", "demo");
// Area demo 的路由注册
public class demoAreaRegistration : AreaRegistration
{
public override string AreaName
{
get { return "demo"; }
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
name: "demo_default",
url: "demo/{controller}/{action}",
defaults: new { controller = "index", action = "index" },
namespaces: new string[] { "xxx.xxx" });
var context2 = new AreaDomainRegistrationContext(context, "demo");
context2.MapRoute(
name: "demo_default",
url: "{controller}/{action}",
defaults: new { controller = "index", action = "index" },
namespaces: new string[] { "xxx.xxx" });
}
}
视图使用 bool b = (string)ViewContext.RouteData.DataTokens["SubDomain"] != null; 可以判断请求是否使用demo.abc.com域名访问
使用 http://demo.abc.com:8098/ 和 http://localhost:8098/demo 都可以访问Area demo