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

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

MVC动态二级域名解析

并且注册区域路由规则

 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 时候就会访问二级域名站点

 

你可能感兴趣的:(mvc)