Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>After thinking of this more, I have a workaround for you. The basic idea of the workaround is to use a route that derives from Route and add it to the RouteCollection directly. That way, the route we are passing will no longer be wrapped inside HttpWebRoute. </p> <p>The RouteByPassing handler is to workaround another known issue. Hope this helps.</p> <pre><code>public static class WebApiConfig { public static void Register(HttpConfiguration config) { config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); RouteTable.Routes.Add("test", new HttpDomainRoute( domain: "{tenant}.auth10.com", routeTemplate: "test", defaults: new { controller = "Values", action = "GetTenant" } )); config.MessageHandlers.Add(new RouteByPassingHandler()); } } public class RouteByPassingHandler : DelegatingHandler { protected override System.Threading.Tasks.Task&lt;HttpResponseMessage&gt; SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) { HttpMessageInvoker invoker = new HttpMessageInvoker(new HttpControllerDispatcher(request.GetConfiguration())); return invoker.SendAsync(request, cancellationToken); } } public class HttpDomainRoute : Route { private Regex domainRegex; private Regex pathRegex; public HttpDomainRoute(string domain, string routeTemplate, object defaults, object constraints = null) : base(routeTemplate, new RouteValueDictionary(defaults), new RouteValueDictionary(constraints), new RouteValueDictionary(), HttpControllerRouteHandler.Instance) { this.Domain = domain; } public string Domain { get; set; } public override RouteData GetRouteData(HttpContextBase context) { // Build regex domainRegex = CreateRegex(this.Domain); pathRegex = CreateRegex(this.Url); // Request information string requestDomain = context.Request.Headers["Host"]; if (!string.IsNullOrEmpty(requestDomain)) { if (requestDomain.IndexOf(":") &gt; 0) { requestDomain = requestDomain.Substring(0, requestDomain.IndexOf(":")); } } else { requestDomain = context.Request.Url.Host; } string requestPath = context.Request.AppRelativeCurrentExecutionFilePath.Substring(2) + context.Request.PathInfo; // Match domain and route Match domainMatch = domainRegex.Match(requestDomain); Match pathMatch = pathRegex.Match(requestPath); // Route data RouteData data = null; if (domainMatch.Success &amp;&amp; pathMatch.Success) { data = base.GetRouteData(context); // Add defaults first if (Defaults != null) { foreach (KeyValuePair&lt;string, object&gt; item in Defaults) { data.Values[item.Key] = item.Value; } } // Iterate matching domain groups for (int i = 1; i &lt; domainMatch.Groups.Count; i++) { Group group = domainMatch.Groups[i]; if (group.Success) { string key = domainRegex.GroupNameFromNumber(i); if (!string.IsNullOrEmpty(key) &amp;&amp; !char.IsNumber(key, 0)) { if (!string.IsNullOrEmpty(group.Value)) { data.Values[key] = group.Value; } } } } // Iterate matching path groups for (int i = 1; i &lt; pathMatch.Groups.Count; i++) { Group group = pathMatch.Groups[i]; if (group.Success) { string key = pathRegex.GroupNameFromNumber(i); if (!string.IsNullOrEmpty(key) &amp;&amp; !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)); } private Regex CreateRegex(string source) { // Perform replacements source = source.Replace("/", @"\/?"); source = source.Replace(".", @"\.?"); source = source.Replace("-", @"\-?"); source = source.Replace("{", @"(?&lt;"); source = source.Replace("}", @"&gt;([a-zA-Z0-9_-]*))"); return new Regex("^" + source + "$"); } private RouteValueDictionary RemoveDomainTokens(RouteValueDictionary values) { 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_-]*})*-?\.?\/?"); Match tokenMatch = tokenRegex.Match(Domain); for (int i = 0; i &lt; tokenMatch.Groups.Count; i++) { Group group = tokenMatch.Groups[i]; if (group.Success) { string key = group.Value.Replace("{", "").Replace("}", ""); if (values.ContainsKey(key)) values.Remove(key); } } return values; } } </code></pre> <p>}</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload