自从微软发布 ASP.NET MVC 和routing engine (System.Web.Routing)以来,就设法让我们明白你完全能控制URL和routing,只要与你的application path相结合进行扩展,任何问题都迎刃而解。如果你需要在所处的域或者子域处理数据标记的话,强制使用Default。

遗憾的是,ASP.NET MVC是基于虚拟目录的,在实际项目却有各种各样的需求方案。

例如:

1:应用程序是多语言的,像cn.example.com应该被匹配到“www.{language}example.com”路由上。

2:应用程序是多用户的,像username.example.com应该被匹配到“www.{clientname}.example.com”路由上。

3:应用程序是多子域的,像mobile.example.com应该被匹配到"www.{controller}.example.com/{action}....” 。

坐下来,深呼吸,开始我们ASP.NET MVC的神奇之旅吧。

定义routes

下面是我们定义简单的route,不带任何controller控制的route:


routes.Add("DomainRoute", new DomainRoute( 
"home.example.com", // Domain with parameters
"{action}/{id}",    // URL with parameters
new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
));

另一个例子是用我们的controller控制域名:


routes.Add("DomainRoute", new DomainRoute( 
"{controller}.example.com",     // Domain with parameters< br />    "{action}/{id}",    // URL with parameters
new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
));

打算用controller 和action完全控制域名?


routes.Add("DomainRoute", new DomainRoute( 
"{controller}-{action}.example.com",     // Domain with parameters
"{id}",    // URL with parameters
new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
));

接下来是多语言route:


routes.Add("DomainRoute", new DomainRoute( 
"{language}.example.com",     // Domain with parameters
"{controller}/{action}/{id}",    // URL with parameters
new { language = "en", controller = "Home", action = "Index", id = "" }  // Parameter defaults
));

HtmlHelper 扩展方法

因为我们不希望所有的URL所产生HtmlHelper ActionLink要使用full URLs,第一件事我们会添加一些新的ActionLink,其中载有boolean flag是否要full URLs或没有。利用这些,现在您可以添加一个链接到一个Action如下:

<%=Html.ActionLink("About", "About", "Home", true)%>

跟你以往的习惯没有什么不同,不是吗?
以下是一小段代码:


public static class LinkExtensions 

public static string ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName, bool requireAbsoluteUrl) 
    { 
return htmlHelper.ActionLink(linkText, actionName, controllerName, new RouteValueDictionary(), new RouteValueDictionary(), requireAbsoluteUrl); 
    }

// more of these

public static string 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;

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); 
    } 
}

在这没什么特别的:有许多的扩展方法,把扩展的URL加到域名上。这是一个预设ActionLink helpers,我的精神食粮来了DomainRoute class(详见:Dark Magic)

Dark magic

瞥眼之间,您可能已经看到了我的DomainRoute类代码段。这个类实际上是提取子域,并增加了象征性支持域部分的传入的URL,

我们将扩展基类,它已经给了我们一些属性和方法,但是我们得重写他们!


public class DomainRoute : Route 
{  
// 

public string Domain { get; set; }

// 

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(":") > 0) 
            { 
                requestDomain = requestDomain.Substring(0, requestDomain.IndexOf(":")); 
            } 
        } 
else
        { 
            requestDomain = httpContext.Request.Url.Host; 
        } 
string requestPath = httpContext.Request.AppRelativeCurrentExecutionFilePath.Substring(2) + httpContext.Request.PathInfo;

//匹配域名和路由

Match domainMatch = domainRegex.Match(requestDomain); 
        Match pathMatch = pathRegex.Match(requestPath);

// Route 数据

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 = 1; 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, 0)) 
                    { 
if (!string.IsNullOrEmpty(group.Value)) 
                        { 
                            data.Values[key] = group.Value; 
                        } 
                    } 
                } 
            }

// 匹配域名路径
for (int i = 1; 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, 0)) 
                    { 
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 = ""
        }; 
    }

// 
}

哇,这是一串按照我们定义的route转换传入请求的URL到tokens的代码,我们这样做是转换{controller}和按照regex然后再尝试匹配route规则,在我们的DomainRoute class里还有其他的helper方法,需要更多的功能可以自己研究扩展。

附代码:附件
(如果要在使用Visual Studio开发Web服务器,务必添加把二级域名添加到hosts文件)(貌似本地测试不用)
原文地址:http://blog.maartenballiauw.be/post/2009/05/20/ASPNET-MVC-Domain-Routing.aspx
其实有的人为什么要这么麻烦用这种方式,URL重写或者二级域名直接绑定都可以。但是既然微软给url rouring,就应该能做到。

转载于:https://www.cnblogs.com/haiyabtx/archive/2013/04/02/2996097.html

ASP.NET MVC 实现二级域名(泛域名)相关推荐

  1. ASP.NET MVC动态二级域名及DNS(泛解析配置)

    动态二级域名的实现: 应用场景:目前产品要实现SaaS功能,因为工作需要实现二级域名:www.{CompanyUrl}.xxx.com 假设产品主域名入口为:www.xxx.com 当a公司租户登录时 ...

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

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

  3. Saas 平台,多域名,泛域名.如何做分站点的统计之解决方案

    最近公司做的Saas新零售平台遇到一个难题就是每个站点要单独做站长统计,而且互相不能查看.每个站点只能查看本站点的统计 所以找了一下最近常用的站点统计工作 百度统计 和cnzz统计发现根本无法实现.他 ...

  4. 多个域名泛域名证书和多域名证书

    现在很多网站经营者已经不止经营一个网站了,所以现在不论是个人或者企业都需要为多个网站的数据安全进行负责,这时候给每个网站单独申请单域名SSL证书并且进行管理就会耗费很多的成本,也不利于管理者对自己旗下 ...

  5. ASP.NET中实现二级或多级域名(修改UrlRewrite)

    大家应该知道,微软的URLRewrite能够对URL进行重写,但是也只能对域名之后的部分进行重写,而不能对域名进行重写,如:可将 http://http://www.abc.com//1234/  重 ...

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

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

  7. 服务器网站泛域名设置,Nginx服务器泛域名配置实例教程

    泛 原本准备换Linux 提示:以下rewrite指令写在 nginx.conf 配置的 server { - } 中 最常见的: 静态地址重定向到带参数的动态地址 rewrite "^(. ...

  8. Let's Encrypt 泛域名证书申请

    泛域名 泛域名证书又名通配符证书是SSL证书中的其中一种形式,一般会以通配符的形式(如:*.domain.com)来指定证书所要保护的域名. OV证书和DV证书都会有通配符的域名形式提供,而EV证书一 ...

  9. 最新版泛域名证书申请

    最新版泛域名证书申请 前言 这几天证书过期了,重新申请了一下,修改了一下之前文档的问题. 泛域名 泛域名证书又名通配符证书是SSL证书中的其中一种形式,一般会以通配符的形式(如:*.domain.co ...

最新文章

  1. linux 9.0挂载驱动
  2. datetime数据类型_系统数据类型
  3. webpack ,gulp
  4. js检测是否安装了flash插件
  5. ACT5.6 动手实验手册 如何在工作组模式下对客户端进行数据收集 如何在AD域环境下对...
  6. web java工程的创建_简单JavaWeb工程创建
  7. linux 进程代码,怎样从Linux终端管理进程:10个你必须知道的命令
  8. 什么是php渲染,php数据渲染输出
  9. 第十节 4基于ashx方式的ASP.Net开发
  10. CSS3知识点总结---transitionend
  11. C++连接MYSQL教程
  12. 叮咚志汇超级外卖餐饮 6.3.8 + 超级跑腿 v2.0.3 打包下载 小程序模块
  13. 微信公众号图片上传和预览功能前端实现
  14. Web服务器群集——LVS-DR+Keepalived高可用集群
  15. 操作系统之经典 | 生产者与消费者问题
  16. WDMycould Gen2安装SVN Server
  17. 当excel不够用时,如何利用Access进行数据分析?
  18. 微信公众号开发教程[001]-引言
  19. 第一次直播完的感受,向小伙伴们致歉!
  20. sfml-tutorials 官方教程的嘟嘟翻译 windows篇

热门文章

  1. dcase_util教程(二)——各单元介绍
  2. gradle之gradlew最全指令攻略
  3. java的abstract的意思_java – spring中的abstract =“true”是什么意思?
  4. mysql客户端版本太低_windows一机多装mysql,5.5低版本+5.8高版本
  5. php取json子对象属性,php中输出json对象的值(实现方法)
  6. Ogre共享骨骼与两种骨骼驱动方法
  7. 矩阵求导与BP的证明的建议
  8. 为什么梯度下降法对于非线性可分数据有效
  9. 高性能Numpy/Scipy加速:使用Intel MKL和Intel Compilers或OpenBLAS(待续)
  10. 工作中的javascript代码收集及整理