自从微软发布 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 parameters new { 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 parameters new { 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 parameters new { 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 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 ) %>
跟你以往的习惯没有什么不同,不是吗? 以下是一小段代码:
Code 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,
我们将扩展基类,它已经给了我们一些属性和方法,但是我们得重写他们!
Code 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,就应该能做到。
转自:http://www.cnblogs.com/luanwey/archive/2009/08/12/1544444.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
2012-11-05 内网的用户不能用外网IP访问内网
2011-11-05 vs2010+Silverlight4+WCF开发部署全过程(转)