博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ASP.NET MVC 实现二级域名
阅读量:7145 次
发布时间:2019-06-29

本文共 5724 字,大约阅读时间需要 19 分钟。

自从微软发布 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:

 

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

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

 

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

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

 

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

接下来是多语言route:

Code
routes.Add("DomainRoute", new DomainRoute( "{language}.example.com",     // Domain with parameters"{controller}/{action}/{id}",    // URL with parametersnew { 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
)
%>

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

 

Code
publicstaticclass LinkExtensions { publicstaticstring 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 thesepublicstaticstring 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,

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

 

Code
publicclass DomainRoute : Route {  // publicstring Domain { get; set; }
// publicoverride 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;     }
publicoverride VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)     { returnbase.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 域名数据returnnew 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,就应该能做到。

转自:

你可能感兴趣的文章
Summer School实验二
查看>>
sed命令的使用及案例
查看>>
GoLang环境配置
查看>>
JAVA构建缓存
查看>>
JS中使用正则表达式
查看>>
我的友情链接
查看>>
VM with share disk configuration
查看>>
解决:Loading kernel module CAP_SYS_MODULE CAP_NET_ADMIN alias netdev-eth0 instead
查看>>
oracle 常用查询
查看>>
QT常用类
查看>>
PHP cURL下载/导出文件
查看>>
java之ArrayList集合
查看>>
系统集成项目管理工程师2011年下半年试题
查看>>
我的友情链接
查看>>
wav2letter-基于深度学习的语音识别
查看>>
二、数据类型
查看>>
多节点CDN缓存加速系统wdcdn2.2版本发布(20111115)
查看>>
Java class.forname()和newinstance
查看>>
Java 命令行编译 获得参数
查看>>
Shell 脚本入二
查看>>