代码改变世界

MVC实现二级域名泛解析

2015-12-09 11:24  莫球名堂  阅读(292)  评论(0编辑  收藏  举报
  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          // Build regex
 35          domainRegex = CreateRegex(Domain);
 36          pathRegex = CreateRegex(Url);
 37  
 38          // Request information
 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          // Match domain and route
 54          Match domainMatch = domainRegex.Match(requestDomain);
 55          Match pathMatch = pathRegex.Match(requestPath);
 56  
 57          // Route data
 58          RouteData data = null;
 59          if (domainMatch.Success && pathMatch.Success)
 60          {
 61              data = new RouteData(this, RouteHandler);
 62  
 63              // Add defaults first
 64              if (Defaults != null)
 65              {
 66                  foreach (KeyValuePair<string, object> item in Defaults)
 67                  {
 68                      data.Values[item.Key] = item.Value;
 69                  }
 70              }
 71  
 72              // Iterate matching domain groups
 73              for (int i = 1; i < domainMatch.Groups.Count; i  )
 74              {
 75                  Group group = domainMatch.Groups[i];
 76                  if (group.Success)
 77                  {
 78                      string key = domainRegex.GroupNameFromNumber(i);
 79  
 80                      if (!string.IsNullOrEmpty(key) && !char.IsNumber(key, 0))
 81                      {
 82                          if (!string.IsNullOrEmpty(group.Value))
 83                          {
 84                              data.Values[key] = group.Value;
 85                          }
 86                      }
 87                  }
 88              }
 89  
 90              // Iterate matching path groups
 91              for (int i = 1; i < pathMatch.Groups.Count; i  )
 92              {
 93                  Group group = pathMatch.Groups[i];
 94                  if (group.Success)
 95                  {
 96                      string key = pathRegex.GroupNameFromNumber(i);
 97  
 98                      if (!string.IsNullOrEmpty(key) && !char.IsNumber(key, 0))
 99                      {
100                          if (!string.IsNullOrEmpty(group.Value))
101                          {
102                              data.Values[key] = group.Value;
103                          }
104                      }
105                  }
106              }
107          }
108  
109          return data;
110      }
111  
112      public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
113      {
114          return base.GetVirtualPath(requestContext, RemoveDomainTokens(values));
115      }
116  
117      public DomainData GetDomainData(RequestContext requestContext, RouteValueDictionary values)
118      {
119          // Build hostname
120          string hostname = Domain;
121          foreach (KeyValuePair<string, object> pair in values)
122          {
123              hostname = hostname.Replace("{"   pair.Key   "}", pair.Value.ToString());
124          }
125  
126          // Return domain data
127          return new DomainData
128          {
129              Protocol = "http",
130              HostName = hostname,
131              Fragment = ""
132          };
133      }
134  
135      private Regex CreateRegex(string source)
136      {
137          // Perform replacements
138          source = source.Replace("/", @"\/?");
139          source = source.Replace(".", @"\.?");
140          source = source.Replace("-", @"\-?");
141          source = source.Replace("{", @"(?<");
142          source = source.Replace("}", @">([a-zA-Z0-9_]*))");
143  
144          return new Regex("^"   source   "$");
145      }
146  
147      private RouteValueDictionary RemoveDomainTokens(RouteValueDictionary values)
148      {
149          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_]*})*-?\.?\/?");
150          Match tokenMatch = tokenRegex.Match(Domain);
151          for (int i = 0; i < tokenMatch.Groups.Count; i  )
152          {
153              Group group = tokenMatch.Groups[i];
154              if (group.Success)
155              {
156                  string key = group.Value.Replace("{", "").Replace("}", "");
157                  if (values.ContainsKey(key))
158                      values.Remove(key);
159              }
160          }
161  
162          return values;
163      }
164  }
View 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
  ));