ASP.NET MVC 实现二级域名
自從微軟發布 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,就應該能做到。
轉自:http://www.cnblogs.com/luanwey/archive/2009/08/12/1544444.html
轉載于:https://www.cnblogs.com/cuihongyu3503319/p/3408400.html
總結
以上是生活随笔為你收集整理的ASP.NET MVC 实现二级域名的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2013-10-31 《三天里什么都没干
- 下一篇: dos下的edit命令使用详解