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%类似,数据同步,很牛很强 ...
随机推荐
- Swift开发小技巧--识别选中照片中的二维码
识别选中照片中的二维码 点击相册按钮,打开用户相册 @IBAction func photoBtnClick(sender: AnyObject) { // 打开相册 // 1.判断是否能够打开相册 ...
- java设计模式(八) 适配器模式
[适配器模式]将一个类的接口,转换成客户期望的另外一个接口.适配器让原本接口不兼容的类可以合作无间. 1,Duck接口 package com.pattern.adapter; public inte ...
- Java设计模式(二) 观察者模式
观察者模式: 定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,他的所有依赖者都会受到通知并自动更新. 1,定义事件源接口 package com.pattern.observer; pub ...
- FastFDFS_Jave客户端调用(亲测可用)
一.配置文件(fdfs_client.properties) 1 2 3 4 5 6 7 8 9 10 connect_timeout = 30 network_timeout = 60 charse ...
- dijkstra 最短路算法
最朴素的做法o(V*V/2+2E)~O(V^2)#include<iostream>using namespace std;#include<vector>#include&l ...
- URI 中特殊字符
URL中的特殊字符 有些符号在URL中是不能直接传递的,如果要在URL中传递这些特殊符号,那么就要使用他们的编码了.编码的格式为:%加字符的ASCII码,即一个百分号%,后面跟对应字符的ASCII(1 ...
- Mysql-linux下密码修改,忘记密码修改,超级管理用户修改
未忘记密码 方法一:在mysql系统外,使用mysqladmin # mysqladmin -u root -p password "test123"Enter password: ...
- 关于Android中图片大小、内存占用与drawable文件夹关系的研究与分析
原文:关于Android中图片大小.内存占用与drawable文件夹关系的研究与分析 相关: Android drawable微技巧,你所不知道的drawable的那些细节 经常会有朋友问我这个问题: ...
- redis事务
当一个client在连接中发出multi命令时,这个连接就进入一个事务的上下文,该连接后续的命令不会执行,而是存放到一个队列中,当执行exec命令时,redis会顺序的执行队列中的所有命令.如果其中执 ...
- 【BZOJ-4521】手机号码 数位DP
4521: [Cqoi2016]手机号码 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 303 Solved: 194[Submit][Status ...