MVC实现动态二级域名
前段时间,一个朋友问我ASP.NET MVC下实现动态二级域名的问题。跟他聊了一些解决方案,这里也总结一下,以供参考。
相信大家都发现类似58同城这样的网站,成都的网址是cd.58.com 上海的是sh.58.com类似的上千个网站,其实没有那么多个网站,域名前面那部分就是泛域名解析,相当于是传递一个参数,所有的域名实际上访问的都是一个网站,仅仅是传递了不一样的参数显示不一样的内容。
比如网站主域名入口为:www.58.com
当成都的用户登录时,解析到:cd.58.com
当上海的用户登录时,则解析到:sh.58.com
首先想到的是对Url的重写:(这在ASP.NET中也是常用的手法。网上有关于UrlRewrite的实现,这里不再重复。)
还有就是MVC 应用程序中的典型URL模式,这里只讨论MVC应用程序URL模式下的动态二级域名实现,测试实例下载。
1.定义DomainData、DomainRoute类
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;
}
} // 匹配域名路由
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;
}
}
}
} // 匹配域名路径
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;
}
}
}
}
} 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)
{
hostname = hostname.Replace("{" + pair.Key + "}", pair.Value.ToString());
} // 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 + "$", RegexOptions.IgnoreCase);
} 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;
}
}
public class DomainData
{
public string Protocol { get; set; }
public string HostName { get; set; }
public string Fragment { get; set; }
}
2.修改RouteConfig,增加如下代码
routes.Add(
"DomainRoute", new DomainRoute(
"{CityNameUrl}.weiz.com",
"{controller}/{action}/{id}",
new { CityNameUrl = "", controller = "City", action = "Index", id = "" }
));
3.增加CityController控制类
public class CityController : Controller
{
public ActionResult Index()
{
var cityName = RouteData.Values["CityNameUrl"];
ViewBag.CityName = cityName;
return View();
}
}
4.发布网站,并修改相关配置
方式一:修改host,我们通过修改host文件,来实现对二级域名的,只能通过一个一个增加解析如:
#host文件
127.0.0.1 www.weiz.com
127.0.0.1 a.weiz.com
127.0.0.1 b.weiz.com
127.0.0.1 c.weiz.com
方式二:增加泛域名解析,配置DNS服务,也就是让你的域名支持泛解析 (Windows Server 才会有,其他的Windows系统只能修改尝试修改Host文件,便于测试) 请看我的另一篇文章《域名泛解析设置》
5. 效果



需要注意:如果你的服务器上有多个站点,则主站不要绑定主机头。其他二级域名的子系统,需要绑定主机头。


MVC实现动态二级域名的更多相关文章
- MVC动态二级域名解析
动态二级域名的实现: 应用场景:目前产品要实现block功能,因为工作需要实现二级域名:www.{CompanyUrl}.xxx.com 假设产品主域名入口为:www.xxx.com 公司员工管理:w ...
- MVC利用Routing实现多域名绑定一个站点、二级域名以及二级域名注册Area
最近有这么个需求:在一个站点上绑定多个域名,每个域名进去后都要进入不同的页面.实现了这个功能以后,对于有多个域名,且有虚拟空间,但是虚拟空间却只匹配有一个站点的用户来说,可以节省很多小钱钱. 很久以前 ...
- asp.net MVC把Areas区域绑定成二级域名
先分析需求 在MVC项目中,我们如果有两个Areas.比如Test和DEMO.我们的访问地址应该是 http://localhost:8098/test http://localhost:8098/d ...
- asp.net core mvc中如何把二级域名绑定到特定的控制器上
由于公司的工作安排,一直在研究其他技术,所以一直没时间更新博客,今天终于可以停下手头的事情,写一些新内容了. 应用场景:企业门户网站会根据内容不同,设置不同的板块,如新浪有体育,娱乐频道,等等.有的情 ...
- mvc 二级域名 重定向
使用mvc开发了一个独立的站点(wechat),但是最后要和并到另外一个站点下(admin),但是外部访问要使用另一个站点(admin)的二级域名 考虑之后采用mvc路由机制来实现(这也要考虑),代码 ...
- 动态DNS——本质上是IP变化,将任意变换的IP地址绑定给一个固定的二级域名。不管这个线路的IP地址怎样变化,因特网用户还是可以使用这个固定的域名 这样看的话,p2p可以用哇
动态域名是因应网络远程访问的需要而产生的一项应用技术.因为没有固定IP,只能运用二级域名来应对经常变化的IP,动态域名的由来因此而产生. 它当前主要应用在:路由器.网络摄像机.带网络监控的硬盘录像机. ...
- ASP.NET MVC3.0或4.0设置二级域名的方法
之前我就想做二级域名指向同一个IP同一个程序无非是在路由匹配规则上做文章也就是对Url的重写的一种思路.我用了半天时间上网查阅了相关资料并做了Demo测试是完全 以的,在这分享给大家... 假如网站主 ...
- Nginx中rewrite实现二级域名、三级域名、泛域名、路径的重写
最常见的: 静态地址重定向到带参数的动态地址 rewrite "^(.*)/service/(.*)\.html$" $1/service.php?sid=$2 permanent ...
- 织梦dedecms移动版设置二级域名的方法 织梦如何设置m.开头的域名
dedecms/' target='_blank'>织梦dedecms建站系统自从2015.06.18号升级后,系统增加了最强的手机站功能,模板与PC模板分开,标签90%类似,数据同步,很牛很强 ...
随机推荐
- idea 新建web项目
- 微信扫码支付 php
仔细看了一遍官方的那幅流程图,我来简化理解一下(注意:我这里针对的是扫码支付模式一,模式二没什么说的)网站后台生成二维码,当然是跟据前台传来的参数有条件的生成买家扫描二维码,扫描过程中,微信后台系统回 ...
- mysql-删除日志文件命令详解
装载 在mysql中会生大量的如mysq-bin.000001这类日志文件了,这些都是二进制文件了,如果我们是普通的日志没有进行主从配置就可以直接使用reset master进行删除了这个方法很简单, ...
- WordPress 博客文章时间格式the_time()设置
国外设计的WordPress 主题里的文章的时间格式是类似“十一月 21, 2010”这种格式的,而中国人习惯的是年在前,月紧跟其后,日在末尾,所以看国外的就显得很别扭,但是我们可以通过修改WP时间代 ...
- css 去除 a,checkbox 框 出现虚线
在开发过程中遇到checkbox框,第一次遇到还以为是系统自带的是这样 后来发现不是那样, 我们可以在使用css 去掉出现的虚线框,以下是我的解决方案代码: /* checkbox 去掉虚框*/:fo ...
- 测试人员如何搭建Selenium-Grid2环境(参考Java)
Selenium对于我们进行web自动化测试有很大的帮助,如果要进行大范围的测试覆盖,就不能仅仅在一两台机器上跑了:同样Selenium-Grid也给我们提供了这样的帮助,我们可以借助Selenium ...
- 【caffe】mnist训练日志
@tags caffe 前面根据train_lenet.sh改写了train_lenet.py后,在根目录下执行它,得到一系列输出,内容如下: I1013 10:05:16.721294 1684 c ...
- 【bzoj1499】 NOI2005—瑰丽华尔兹
http://www.lydsy.com/JudgeOnline/problem.php?id=1499 (题目链接) 题意 给出一个n*m的地图,刚开始人在(x,y),每次给出一段区间(l,r,t) ...
- codeforces 342E :Xenia and Tree
Description Xenia the programmer has a tree consisting of n nodes. We will consider the tree nodes i ...
- Android成长日记-使用ToggleButton实现灯的开关
案例演示 此案例实现思路:通过ToggleButton控件,ImageView控件实现 ---xml代码: <!-- textOn:true textOff:falase[s1] --> ...