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 }