参考:https://blog.maartenballiauw.be/post/2009/05/20/aspnet-mvc-domain-routing.html

参考:https://www.cnblogs.com/Showshare/p/multidomain-to-onesite-subdomain-to-area-by-routing.html

适当使用反编译工具查看 Route 的源码

主要类

DomainData.cs

namespace DomainMvcTest.Core
{
public class DomainData
{
public string Protocol { get; set; }
public string HostName { get; set; }
public string Fragment { get; set; }
}
}

DomainRoute.cs

using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing; namespace DomainMvcTest.Core
{
public class DomainRoute : Route
{
private Regex domainRegex;
private Regex pathRegex; public string Domain { get; set; } public DomainRoute(string domain, string url, RouteValueDictionary defaults)
: base(url, defaults, new MvcRouteHandler())
{
Domain = domain;
} public DomainRoute(string domain, string url, RouteValueDictionary defaults, IRouteHandler routeHandler)
: base(url, defaults, routeHandler)
{
Domain = domain;
} public DomainRoute(string domain, string url, object defaults)
: base(url, new RouteValueDictionary(defaults), new MvcRouteHandler())
{
Domain = domain;
} public DomainRoute(string domain, string url, object defaults, IRouteHandler routeHandler)
: base(url, new RouteValueDictionary(defaults), routeHandler)
{
Domain = domain;
} public override RouteData GetRouteData(HttpContextBase httpContext)
{
// 构造 regex
domainRegex = CreateRegex(Domain);
pathRegex = CreateRegex(Url); // 请求信息
string requestDomain = httpContext.Request.Headers["host"];
if (!string.IsNullOrEmpty(requestDomain))
{
if (requestDomain.IndexOf(":") > )
{
requestDomain = requestDomain.Substring(, requestDomain.IndexOf(":"));
}
}
else
{
requestDomain = httpContext.Request.Url.Host;
}
string requestPath = httpContext.Request.AppRelativeCurrentExecutionFilePath.Substring() + httpContext.Request.PathInfo; // 匹配域名和路由
Match domainMatch = domainRegex.Match(requestDomain);
Match pathMatch = pathRegex.Match(requestPath); // 路由数据
RouteData data = null;
if (domainMatch.Success && pathMatch.Success)
{
data = new RouteData(this, RouteHandler); // 添加默认选项
if (Defaults != null)
{
foreach (KeyValuePair<string, object> item in Defaults)
{
data.Values[item.Key] = item.Value;
if (item.Key.Equals("area") || item.Key.Equals("Namespaces"))
{
data.DataTokens[item.Key] = item.Value;
}
}
} // 匹配域名
for (int i = ; i < domainMatch.Groups.Count; i++)
{
Group group = domainMatch.Groups[i];
if (group.Success)
{
string key = domainRegex.GroupNameFromNumber(i); if (!string.IsNullOrEmpty(key) && !char.IsNumber(key, ))
{
if (!string.IsNullOrEmpty(group.Value))
{
data.Values[key] = group.Value;
if (key.Equals("area"))
{
data.DataTokens[key] = group.Value;
}
}
}
}
} // 匹配路径
for (int i = ; i < pathMatch.Groups.Count; i++)
{
Group group = pathMatch.Groups[i];
if (group.Success)
{
string key = pathRegex.GroupNameFromNumber(i); if (!string.IsNullOrEmpty(key) && !char.IsNumber(key, ))
{
if (!string.IsNullOrEmpty(group.Value))
{
data.Values[key] = group.Value;
if (key.Equals("area"))
{
data.DataTokens[key] = group.Value;
}
}
}
}
}
} return data;
} public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
return base.GetVirtualPath(requestContext, RemoveDomainTokens(values));
} public DomainData GetDomainData(RequestContext requestContext, RouteValueDictionary values)
{
// 获得主机名
string hostname = Domain;
foreach (KeyValuePair<string, object> pair in values)
{
if (pair.Key == "area" && string.IsNullOrEmpty(pair.Value.ToString()))
{
hostname = hostname.Replace("{" + pair.Key + "}", "www");
}
else
{
hostname = hostname.Replace("{" + pair.Key + "}", pair.Value.ToString());
}
} //如果域名的area还没有被替换,说明路由数据里没有area,恢复为顶级域名
if (hostname.Contains("{area}"))
{
hostname = hostname.Replace("{area}", "www");
} RemoveDomainTokens(values); // Return 域名数据
return new DomainData
{
Protocol = "http",
HostName = hostname,
Fragment = ""
};
} private Regex CreateRegex(string source)
{
// 替换
source = source.Replace("/", @"\/?");
source = source.Replace(".", @"\.?");
source = source.Replace("-", @"\-?");
source = source.Replace("{", @"(?<");
source = source.Replace("}", @">([a-zA-Z0-9_]*))"); return new Regex("^" + source + "$");
} private RouteValueDictionary RemoveDomainTokens(RouteValueDictionary values)
{
Regex tokenRegex = new Regex(@"({[a-zA-Z0-9_]*})*-?\.?\/?({[a-zA-Z0-9_]*})*-?\.?\/?({[a-zA-Z0-9_]*})*-?\.?\/?({[a-zA-Z0-9_]*})*-?\.?\/?({[a-zA-Z0-9_]*})*-?\.?\/?({[a-zA-Z0-9_]*})*-?\.?\/?({[a-zA-Z0-9_]*})*-?\.?\/?({[a-zA-Z0-9_]*})*-?\.?\/?({[a-zA-Z0-9_]*})*-?\.?\/?({[a-zA-Z0-9_]*})*-?\.?\/?({[a-zA-Z0-9_]*})*-?\.?\/?({[a-zA-Z0-9_]*})*-?\.?\/?");
Match tokenMatch = tokenRegex.Match(Domain);
for (int i = ; i < tokenMatch.Groups.Count; i++)
{
Group group = tokenMatch.Groups[i];
if (group.Success)
{
string key = group.Value.Replace("{", "").Replace("}", "");
if (values.ContainsKey(key))
values.Remove(key);
}
} return values;
}
}
}

LinkExtensions.cs

using System.Collections.Generic;
using System.Linq;
using System.Web.Routing;
using DomainMvcTest.Core; namespace System.Web.Mvc.Html
{
public static class LinkExtensions
{
public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, bool requireAbsoluteUrl)
{
return htmlHelper.ActionLink(linkText, actionName, null, new RouteValueDictionary(), new RouteValueDictionary(), requireAbsoluteUrl);
} public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, object routeValues, bool requireAbsoluteUrl)
{
return htmlHelper.ActionLink(linkText, actionName, null, new RouteValueDictionary(routeValues), new RouteValueDictionary(), requireAbsoluteUrl);
} public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName, bool requireAbsoluteUrl)
{
return htmlHelper.ActionLink(linkText, actionName, controllerName, new RouteValueDictionary(), new RouteValueDictionary(), requireAbsoluteUrl);
} public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, RouteValueDictionary routeValues, bool requireAbsoluteUrl)
{
return htmlHelper.ActionLink(linkText, actionName, null, routeValues, new RouteValueDictionary(), requireAbsoluteUrl);
} public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, object routeValues, object htmlAttributes, bool requireAbsoluteUrl)
{
return htmlHelper.ActionLink(linkText, actionName, null, new RouteValueDictionary(routeValues), new RouteValueDictionary(htmlAttributes), requireAbsoluteUrl);
} public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, RouteValueDictionary routeValues, IDictionary<string, object> htmlAttributes, bool requireAbsoluteUrl)
{
return htmlHelper.ActionLink(linkText, actionName, null, routeValues, htmlAttributes, requireAbsoluteUrl);
} public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName, object routeValues, object htmlAttributes, bool requireAbsoluteUrl)
{
return htmlHelper.ActionLink(linkText, actionName, controllerName, new RouteValueDictionary(routeValues), new RouteValueDictionary(htmlAttributes), requireAbsoluteUrl);
} public static MvcHtmlString ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName, RouteValueDictionary routeValues, IDictionary<string, object> htmlAttributes, bool requireAbsoluteUrl)
{
if (requireAbsoluteUrl)
{
HttpContextBase currentContext = new HttpContextWrapper(HttpContext.Current);
RouteData routeData = RouteTable.Routes.GetRouteData(currentContext); routeData.Values["controller"] = controllerName;
routeData.Values["action"] = actionName;
//如果不需要变换area,则routeValues不传入area的值
if (routeValues.Keys.Contains("area"))
{
routeData.Values["area"] = routeValues["area"];
} DomainRoute domainRoute = routeData.Route as DomainRoute;
if (domainRoute != null)
{
DomainData domainData = domainRoute.GetDomainData(new RequestContext(currentContext, routeData), routeData.Values);
return htmlHelper.ActionLink(linkText, actionName, controllerName, domainData.Protocol, domainData.HostName, domainData.Fragment, routeData.Values, null);
}
}
return htmlHelper.ActionLink(linkText, actionName, controllerName, routeValues, htmlAttributes);
}
}
}

在 AreaRegistration 中注册路由

using System.Web.Mvc;
using DomainMvcTest.Core; namespace DomainMvcTest.Areas.Haha
{
public class HahaAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "Haha";
}
} public override void RegisterArea(AreaRegistrationContext context)
{
context.Routes.Add("hahaDomain", new DomainRoute(
"{area}.chenwei.com", // Domain with parameters
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = "", Namespaces = new[] { "DomainMvcTest.Areas.Haha.Controllers" }} // Parameter defaults
));
//context.MapRoute(
// "Haha_default",
// "Haha/{controller}/{action}/{id}",
// new { action = "Index", id = UrlParameter.Optional }
//);
}
}
}

View 中生成Url连接

    @Html.ActionLink("前往首页", "Index", "Home",new{area=""},null,true) <br/>
@Html.ActionLink("前往Hehe", "Index", "Home", new { area = "Hehe" }, null, true)<br />
@Html.ActionLink("前往Haha", "Index", "Home", new { area = "Haha" }, null, true)

Asp.Net Mvc Area二级域名的更多相关文章

  1. ASP.NET MVC 实现二级域名

      自从微软发布 ASP.NET MVC 和routing engine (System.Web.Routing)以来,就设法让我们明白你完全能控制URL和routing,只要与你的applicati ...

  2. ASP.NET MVC Area使用-将Area设置成独立项目

    环境说明:Vistual Studio 2013 MVC 4.0 其实关于ASP.NET MVC Area使用的基础知识可以参考 http://www.cnblogs.com/willick/p/33 ...

  3. ASP.NET MVC Area 区域

    大型网站或项目通常有很多子系统或功能模块,如大型网站可能包含酒店.旅游.机票子系统,通过二级域名来访问,或者一个网站的前台和后台模块,每个团队负责某一子系统或模块,为了各团队进行协同开发,我们可以分不 ...

  4. ASP.NET MVC Area 的使用

    MVC提供Area机制,在同一个项目之内就能够切割出不同的ASP.NET MVC网站. 插入:首先在相同的位置,比如说同一个文件夹(如:Controllers)是不能创建俩个相同名称的文件(如:Hom ...

  5. Asp.net MVC area

    妈的,今天去携程面试,技术面了三轮,竟然让我走了,没有然后了,你不要老子,干嘛还面那么多轮,害的老子一上午的时间没了,气死我了. 好了,总结下面试中的问题吧, 1.GC 2.设计模式 3.做过的项目的 ...

  6. 实现asp.net mvc页面二级缓存,提高访问性能

    实现的mvc二级缓存的类 //Asp.Net MVC视图页面二级缓存 public class TwoLevelViewCache : IViewLocationCache { private rea ...

  7. asp.net mvc area实现多级controller和多级view

    经常需要描述这样的项目结构 ~:. //web根目录├─.admin   //管理员功能目录│  └─index.html    //管理员目录页面├─.user                  / ...

  8. asp.net Mvc Area 找到多个与名为相同的控制器匹配的类型 请通过调用含有“namespaces”参数

    MVC中的Area的区域的时候,在一个Area中定义了一个Home控制器,在启动的时候, 找到多个与名为"Home"的控制器匹配的类型.如果为此请求("{controll ...

  9. MVC利用Routing实现多域名绑定一个站点、二级域名以及二级域名注册Area

    最近有这么个需求:在一个站点上绑定多个域名,每个域名进去后都要进入不同的页面.实现了这个功能以后,对于有多个域名,且有虚拟空间,但是虚拟空间却只匹配有一个站点的用户来说,可以节省很多小钱钱. 很久以前 ...

随机推荐

  1. JS正则表达式使用

    <script type="text/javascript"> function SubmitCk() { var reg = /^([a-zA-Z0-9]+[_|\_ ...

  2. python : 设计模式之外观模式(Facade Pattern)

    #为啥要用外观模式举例说明 这个例子很形象,直接从人家博客上贴过来的,参考链接在下面 不知道大家有没有比较过自己泡茶和去茶馆喝茶的区别,如果是自己泡茶需要自行准备茶叶.茶具和开水,如图1(A)所示,而 ...

  3. Docs-.NET-C#-指南-语言参考-关键字-值类型:char

    ylbtech-Docs-.NET-C#-指南-语言参考-关键字-值类型:char 1.返回顶部 1. char(C# 参考) 2019/10/22 char 类型关键字是 .NET System.C ...

  4. percona-mysql5.7.24使用xtrabackup工具配置主从同步

    主从配置详细过程: 环境准备: 配置好服务器,主从服务器都安装并启动mysql数据库 # 添加读写账号和只读账号,应用配置中,写主库用读写账号,统计从库数据yoga只读账号 grant select, ...

  5. IDEA中spring约束文件报红 的解决办法

  6. 软件定义网络基础---SDN数据平面

    主要介绍SDN架构和转发模型 一:传统网络设备 (一)传统设备控制平面和数据平面 (二)数据平面的任务 数据平面对数据包的处理,主要通过查询由控制平面所生成的转发信息表来完成 (三)传统网络数据平面数 ...

  7. k8s记录-flanneld+docker网络部署(四)

    1)程序准备tar xvf flannel-v0.10.0-linux-amd64.tar.gz mkdir -p /data/projects/common/kubernetes/{bin,cfg, ...

  8. iOS 不允许横屏的简单代码

    - (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWi ...

  9. django.db.utils.OperationalError: (1251, 'Client does not support authentication protocol requested by server; consider upgrading MySQL client')

    1.打开MySQL: cmd里 net start mysql mysql -hlocalhost -uroot -p回车 进入mysql数据库 2. 命令如下: 1.use mysql; 2.alt ...

  10. Flink 在IDEA执行时的webui

    不过Flink IDEA中执行的webui 需要 flink-runtime-web 包的支持 pom 如下: <dependency> <groupId>org.apache ...