MVC动态二级域名解析

动态二级域名的实现:

应用场景:目前产品要实现block功能,因为工作需要实现二级域名:www.{CompanyUrl}.xxx.com

假设产品主域名入口为:www.xxx.com

公司员工管理:www.a.xxx.com

公司产品管理: www.b.xxx.com

Route简介:ASP.NET路由可以不用映射到网站特定文件的URL.由于该 URL 不必映射到文件,因此可以使用对用户操作进行描述因而更易于被用户理解的 URL。.NET Framework 3.5 SP1已经包含了ASP.NET Routing引擎。现在微软已经在ASP.NET WebForms 4.0中增加了对Routing引擎更好的支持,它使用表达式构造器进行双向Routing。
MVC 应用程序中的典型 URL 模式——来自MSDN

MVC 应用程序中用于路由的 URL 模式通常包括 {controller} 和 {action} 占位符。

当收到请求时,会将其路由到 UrlRoutingModule 对象,然后路由到 MvcHandler HTTP 处理程序。 MvcHandler HTTP 处理程序通过向 URL 中的控制器值添加后缀“Controller”以确定将处理请求的控制器的类型名称,来确定要调用的控制器。URL 中的操作值确定要调用的操作方法。

MVC项目中添加路由,Global.asax 文件默认的MVC 路由的代码。

默认配置:

 1 public static void RegisterRoutes(RouteCollection routes)
 2 {
 3     routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
 4     
 5     routes.MapRoute(
 6         "Default", // Route name
 7         "{controller}/{action}/{id}", // URL with parameters
 8         new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
 9     );
10     
11 }

 

1 protected void Application_Start()
2 {
3     AreaRegistration.RegisterAllAreas();
4     
5     RegisterGlobalFilters(GlobalFilters.Filters);
6     RegisterRoutes(RouteTable.Routes);
7 }

 

涉及类参考

说明
Route 表示 Web 窗体或 MVC 应用程序中的路由。
RouteBase 用作表示 ASP.NET 路由的所有类的基类。
RouteTable 存储应用程序的路由。
RouteData 包含所请求路由的值。
RequestContext 包含有关对应于路由的 HTTP 请求的信息。
RouteValueDictionary 提供用于存储路由 Constraints、Defaults 和 DataTokens 对象的方法。
VirtualPathData 提供用于从路由信息生成 URL 的方法。

因为目前采用的是ASP.NET MVC 3进而可以利用扩展Route的方式实现。

首先定义DomainData、DomainRoute类

代码如下:

DomainRoute类:

  1     public class DomainRoute : Route
  2     {
  3         private Regex domainRegex;
  4         private Regex pathRegex;
  5 
  6         public string Domain { get; set; }
  7 
  8         public DomainRoute(string domain, string url, RouteValueDictionary defaults)
  9             : base(url, defaults, new MvcRouteHandler())
 10         {
 11             Domain = domain;
 12         }
 13 
 14         public DomainRoute(string domain, string url, RouteValueDictionary defaults, IRouteHandler routeHandler)
 15             : base(url, defaults, routeHandler)
 16         {
 17             Domain = domain;
 18         }
 19 
 20         public DomainRoute(string domain, string url, object defaults)
 21             : base(url, new RouteValueDictionary(defaults), new MvcRouteHandler())
 22         {
 23             Domain = domain;
 24         }
 25 
 26         public DomainRoute(string domain, string url, object defaults, IRouteHandler routeHandler)
 27             : base(url, new RouteValueDictionary(defaults), routeHandler)
 28         {
 29             Domain = domain;
 30         }
 31 
 32         public override RouteData GetRouteData(HttpContextBase httpContext)
 33         {
 34             // 构造 regex
 35             domainRegex = CreateRegex(Domain);
 36             pathRegex = CreateRegex(Url);
 37 
 38             // 请求信息
 39             string requestDomain = httpContext.Request.Headers["host"];
 40             if (!string.IsNullOrEmpty(requestDomain))
 41             {
 42                 if (requestDomain.IndexOf(":") > 0)
 43                 {
 44                     requestDomain = requestDomain.Substring(0, requestDomain.IndexOf(":"));
 45                 }
 46             }
 47             else
 48             {
 49                 requestDomain = httpContext.Request.Url.Host;
 50             }
 51             string requestPath = httpContext.Request.AppRelativeCurrentExecutionFilePath.Substring(2) + httpContext.Request.PathInfo;
 52 
 53             // 匹配域名和路由
 54             Match domainMatch = domainRegex.Match(requestDomain);
 55             Match pathMatch = pathRegex.Match(requestPath);
 56 
 57             // 路由数据
 58             RouteData data = null;
 59             if (domainMatch.Success && pathMatch.Success)
 60             {
 61                 data = new RouteData(this, RouteHandler);
 62 
 63                 // 添加默认选项
 64                 if (Defaults != null)
 65                 {
 66                     foreach (KeyValuePair<string, object> item in Defaults)
 67                     {
 68                         data.Values[item.Key] = item.Value;
 69                         if (item.Key.Equals("area") || item.Key.Equals("namespaces"))
 70                         {
 71                             data.DataTokens[item.Key] = item.Value;
 72                         }
 73                     }
 74                 }
 75 
 76                 // 匹配域名路由
 77                 for (int i = 1; i < domainMatch.Groups.Count; i++)
 78                 {
 79                     Group group = domainMatch.Groups[i];
 80                     if (group.Success)
 81                     {
 82                         string key = domainRegex.GroupNameFromNumber(i);
 83 
 84                         if (!string.IsNullOrEmpty(key) && !char.IsNumber(key, 0))
 85                         {
 86                             if (!string.IsNullOrEmpty(group.Value))
 87                             {
 88                                 data.Values[key] = group.Value;
 89                                 if (key.Equals("area"))
 90                                 {
 91                                     data.DataTokens[key] = group.Value;
 92                                 }
 93                             }
 94                         }
 95                     }
 96                 }
 97 
 98                 // 匹配域名路径
 99                 for (int i = 1; i < pathMatch.Groups.Count; i++)
100                 {
101                     Group group = pathMatch.Groups[i];
102                     if (group.Success)
103                     {
104                         string key = pathRegex.GroupNameFromNumber(i);
105 
106                         if (!string.IsNullOrEmpty(key) && !char.IsNumber(key, 0))
107                         {
108                             if (!string.IsNullOrEmpty(group.Value))
109                             {
110                                 data.Values[key] = group.Value;
111                                 if (key.Equals("area"))
112                                 {
113                                     data.DataTokens[key] = group.Value;
114                                 }
115                             }
116                         }
117                     }
118                 }
119             }
120 
121             return data;
122         }
123 
124         public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
125         {
126             return base.GetVirtualPath(requestContext, RemoveDomainTokens(values));
127         }
128 
129         //public DomainData GetDomainData(RequestContext requestContext, RouteValueDictionary values)
130         //{
131         //    // 获得主机名
132         //    string hostname = Domain;
133         //    foreach (KeyValuePair<string, object> pair in values)
134         //    {
135         //        hostname = hostname.Replace("{" + pair.Key + "}", pair.Value.ToString());
136         //    }
137 
138         //    // Return 域名数据
139         //    return new DomainData
140         //    {
141         //        Protocol = "http",
142         //        HostName = hostname,
143         //        Fragment = ""
144         //    };
145         //}
146 
147         private Regex CreateRegex(string source)
148         {
149             // 替换
150             source = source.Replace("/", @"\/?");
151             source = source.Replace(".", @"\.?");
152             source = source.Replace("-", @"\-?");
153             source = source.Replace("{", @"(?<");
154             source = source.Replace("}", @">([a-zA-Z0-9_]*))");
155 
156             return new Regex("^" + source + "$");
157         }
158 
159         private RouteValueDictionary RemoveDomainTokens(RouteValueDictionary values)
160         {
161             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_]*})*-?\.?\/?");
162             Match tokenMatch = tokenRegex.Match(Domain);
163             for (int i = 0; i < tokenMatch.Groups.Count; i++)
164             {
165                 Group group = tokenMatch.Groups[i];
166                 if (group.Success)
167                 {
168                     string key = group.Value.Replace("{", "").Replace("}", "");
169                     if (values.ContainsKey(key))
170                         values.Remove(key);
171                 }
172             }
173 
174             return values;
175         }
176     }
View Code

然后注册我的产品管理系统

并且注册区域路由规则

 1     public class BlockAreaRegistration : AreaRegistration
 2     {
 3         public override string AreaName
 4         {
 5             get
 6             {
 7                 return "Block";
 8             }
 9         }
10 
11         public override void RegisterArea(AreaRegistrationContext context)
12         {
13             context.Routes.Add(new DomainRoute(
14                "us.block.com",     // Domain with parameters 需要配置host文件 
15                "{controller}/{action}/{id}",    // URL with parameters 
16                new
17                {
18                    area = "Block",
19                    controller = "Default",
20                    action = "Index",
21                    id = UrlParameter.Optional,
22                    namespaces = new[] { "Notify.Solution.WebMvc.Areas.Block.Controllers" }
23                }));
24         }
25     }
View Code

当用户访问www.Block.com 时候就会访问主站点

当用户访问us.Block.com 时候就会访问二级域名站点

 

posted @ 2015-06-15 11:25  刘小吉  阅读(1039)  评论(0编辑  收藏  举报