Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>So after quite some time I solved this issue by myself on the application level. IIS rewrites werent working, ASP MVC wasnt matching the right route and it would 404 out.</p> <p>The solution that worked for me in the end was to make my own implementation of the route class, one that searches the hostname for a parametar and maps it as a route parametar. It works flawlessly now and the custom implemenation is simple. I fell in love with the flexibilty ASP MVC gives you in the process :)</p> <p>So a custom route needs two overrides one for the method "GetRouteData" which matches an incoming route and the second one "GetVirtualPath" that writes outgoing routes.</p> <p>Here is the whole custom route class:</p> <pre><code>using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace System.Web.Routing { public class WildcardRoute : Route { public WildcardRoute(string url, IRouteHandler handler) : base(url, handler) { } public WildcardRoute(string url, RouteValueDictionary defaults, IRouteHandler handler) : base(url, defaults, handler) { } public WildcardRoute(string url, RouteValueDictionary defaults, RouteValueDictionary constraints, IRouteHandler handler) : base(url, defaults, constraints, handler) { } public WildcardRoute(string url, RouteValueDictionary defaults, RouteValueDictionary constraints, RouteValueDictionary dataTokens, IRouteHandler handler) : base(url, defaults, constraints, dataTokens, handler) { } public override RouteData GetRouteData(HttpContextBase httpContext) { // save the original path before we edit it var orignalPath = HttpContext.Current.Request.Path; //split the hostname var split = HttpContext.Current.Request.Url.Host.Split('.'); // fire only if there is more than 2 items in the split (company.mydomain.com) and if the first one is not www if (split.Count() &gt; 2 &amp;&amp; split[0].ToLower() != "www") { var split2 = HttpContext.Current.Request.Path.Split('/'); // split everything after the hostname into segments string newPath = "/" + split[0]; // take the company from company.mydomain.com and rewrite it to mydomain.com/company foreach (var item in split2) // add all the other segments that come after mydomain.com/company { // end result might be for example - mydomain.com/company/Home/Index newPath = newPath + "/" + item; } httpContext.RewritePath(newPath); // rewrite the path into the newone } RouteData data = base.GetRouteData(httpContext); // match the route with the new path if (data == null) // if there is no match in this route write the path back to the original one { httpContext.RewritePath(orignalPath); } return data; } public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values) { var data = base.GetVirtualPath(requestContext, values); // do the original url write var split = requestContext.HttpContext.Request.Url.Host.Split('.'); // split the host by '.' var item = requestContext.RouteData.Values.FirstOrDefault(x =&gt; x.Key == "PermalinkTitle"); // the PermalinkTitle is the name of the "company" route value in mydomain.com/company in my implementation if (split.Count() &gt; 0 &amp;&amp; split[0].ToLower().Contains(item.Value.ToString().ToLower())) // fire only if the hostname contains the "company" route value { data.VirtualPath = data.VirtualPath.Replace(item.Value.ToString(), ""); if (data.VirtualPath.StartsWith("/")) data.VirtualPath = data.VirtualPath.Substring(1); // this code removes the company part from the path so we dont get company.mydomain.com/company/controller/action rather we just get company.mydomain.com/controller/action } return data; } } } </code></pre> <p>This implementation is flexible enough that its gonna work with all of these routes - "company.mydomain.com", "mydomain.com/company" and "www.mydomain.com/company".</p> <p>After you made your custom route class you need to extend the RouteCollection with a Map method that maps your custom type of route, you also need to extend the AreaRegistrationContext if you use Areas, becouse with areas route mapping goes through that. Here is the whole implementation:</p> <pre><code>using System; using System.Web.Mvc; using System.Web.Routing; namespace System.Web.Routing { public static class WildcardRoutesExtension { public static WildcardRoute MapWildcardRoute(this RouteCollection routes, string name, string url, object defaults) { WildcardRoute route = new WildcardRoute( url, new RouteValueDictionary(defaults), new MvcRouteHandler()); routes.Add(name, route); return route; } public static WildcardRoute MapWildcardRoute(this AreaRegistrationContext context, string name, string url, object defaults) { WildcardRoute route = new WildcardRoute( url, new RouteValueDictionary(defaults), new RouteValueDictionary(new {}), new RouteValueDictionary(new {Area = context.AreaName }), new MvcRouteHandler()); context.Routes.Add(name, route); return route; } public static WildcardRoute MapWildcardRoute(this AreaRegistrationContext context, string name, string url, object defaults, object constraints) { WildcardRoute route = new WildcardRoute( url, new RouteValueDictionary(defaults), new RouteValueDictionary(constraints), new RouteValueDictionary(new {Area = context.AreaName }), new MvcRouteHandler()); context.Routes.Add(name, route); return route; } public static WildcardRoute MapWildcardRoute(this RouteCollection routes, string name, string url, object defaults, object constraints) { WildcardRoute route = new WildcardRoute( url, new RouteValueDictionary(defaults), new RouteValueDictionary(constraints), new MvcRouteHandler()); routes.Add(name, route); return route; } } } </code></pre> <p>When you have all of this you now just need to map your custom routes like this for regular routes in the RouteConfig class:</p> <pre><code> public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { // rest of your routes routes.MapWildcardRoute( name: "Default", url: "{PermalinkTitle}/{controller}/{action}", defaults: new { } ); //Rest of your routes } </code></pre> <p>or like this for areas in the Areas AreaRegistration class:</p> <pre><code> public override void RegisterArea(AreaRegistrationContext context) { context.MapWildcardRoute( "MyArea_default", "{PermalinkTitle}/MyArea/{controller}/{action}/{id}", new { action = "Index", id = UrlParameter.Optional } ); } </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

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