Asp.Net Mvc Area二级域名
参考: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二级域名的更多相关文章
- ASP.NET MVC 实现二级域名
自从微软发布 ASP.NET MVC 和routing engine (System.Web.Routing)以来,就设法让我们明白你完全能控制URL和routing,只要与你的applicati ...
- ASP.NET MVC Area使用-将Area设置成独立项目
环境说明:Vistual Studio 2013 MVC 4.0 其实关于ASP.NET MVC Area使用的基础知识可以参考 http://www.cnblogs.com/willick/p/33 ...
- ASP.NET MVC Area 区域
大型网站或项目通常有很多子系统或功能模块,如大型网站可能包含酒店.旅游.机票子系统,通过二级域名来访问,或者一个网站的前台和后台模块,每个团队负责某一子系统或模块,为了各团队进行协同开发,我们可以分不 ...
- ASP.NET MVC Area 的使用
MVC提供Area机制,在同一个项目之内就能够切割出不同的ASP.NET MVC网站. 插入:首先在相同的位置,比如说同一个文件夹(如:Controllers)是不能创建俩个相同名称的文件(如:Hom ...
- Asp.net MVC area
妈的,今天去携程面试,技术面了三轮,竟然让我走了,没有然后了,你不要老子,干嘛还面那么多轮,害的老子一上午的时间没了,气死我了. 好了,总结下面试中的问题吧, 1.GC 2.设计模式 3.做过的项目的 ...
- 实现asp.net mvc页面二级缓存,提高访问性能
实现的mvc二级缓存的类 //Asp.Net MVC视图页面二级缓存 public class TwoLevelViewCache : IViewLocationCache { private rea ...
- asp.net mvc area实现多级controller和多级view
经常需要描述这样的项目结构 ~:. //web根目录├─.admin //管理员功能目录│ └─index.html //管理员目录页面├─.user / ...
- asp.net Mvc Area 找到多个与名为相同的控制器匹配的类型 请通过调用含有“namespaces”参数
MVC中的Area的区域的时候,在一个Area中定义了一个Home控制器,在启动的时候, 找到多个与名为"Home"的控制器匹配的类型.如果为此请求("{controll ...
- MVC利用Routing实现多域名绑定一个站点、二级域名以及二级域名注册Area
最近有这么个需求:在一个站点上绑定多个域名,每个域名进去后都要进入不同的页面.实现了这个功能以后,对于有多个域名,且有虚拟空间,但是虚拟空间却只匹配有一个站点的用户来说,可以节省很多小钱钱. 很久以前 ...
随机推荐
- macos下如何解决无法写ntfs格式的u盘或硬盘?
答:macos原生支持,可以通过脚本卸载再重新挂载为可读写即可,脚本在此
- 各类型变量所占字节数,sizeof()
与操作系统位数和编译器都有关. 可用sizeof()得到,当前主流编译器一般是32位或64位. 类型 16位 32位 64位 char 1 1 1 sho ...
- [转]EL表达式判断是否为空,判断是否为空字符串
原文地址:https://blog.csdn.net/zhaofuqiangmycomm/article/details/79442730 El表达式判断是否为空字符串 ${empty 值} 返回t ...
- MWC飞控增加声纳定高的方法(转)
源: MWC飞控增加声纳定高的方法
- git pull There is no tracking information for the current branch.
在高版本的 git下面,也许会看见这样的提示: 解决方案:指定当前工作目录工作分支,跟远程的仓库,分支之间的链接关系. 比如我们设置master对应远程仓库的master分支 git branch - ...
- SNAT场景模拟
我的网络配置跟教程中的这个略有不同: web server:192.168.66.101 nat server:192.168.66.188:192.168.6.172 client:192.168. ...
- Android Support v4、v7、v13、v14、v17的区别和应用场景
Android Support v4.v7.v13.v14.v17的区别和应用场景 本文链接:https://blog.csdn.net/Aquarius_Seven/article/detail ...
- Django安全配置(settings.py)详解
必须配置项 PASSWORD_HASHER 这个配置是在使用Django自带的密码加密函数的时候会使用的加密算法的列表.默认如下: PASSWORD_HASHERS = ( 'django.contr ...
- mybatis 枚举typeHandler
枚举typeHandler 在绝大多数情况下,typeHandler因为枚举而使用,MyBatis已经定义了两个类作为枚举类型的支持,这两个类分别是: •EnumOrdinalTypeHandler. ...
- Flink统计当日的UV、PV
Flink 统计当日的UV.PV 测试环境: flink 1.7.2 1.数据流程 a.模拟数据生成,发送到kafka(json 格式) b.flink 读取数据,count c. 输出数据到kafk ...