2009-11-30 14 views
10

Ich bin ziemlich neu in asp.net und habe wenig Erfahrung mit IIS. Ich möchte, dass jeder Benutzer meiner Anwendung eine eigene Subdomain erhält, aber alle verwenden die gleichen Controller. Die Subdomain würde dann steuern, welcher Inhalt angezeigt wird.Dynamische Subdomains in asp.net mvc

Beispiel:

user1subdomain.mydomain.com/Whatever 
user2subdomain.mydomain.com/Whatever 

Werden beide den gleichen Controller. Idealerweise könnte ein Parameter dem Controller den Benutzernamen geben, der dann den passenden Inhalt anzeigen könnte. Ich möchte, dass es flexibel genug ist, dass neue Subdomains der Datenbank hinzugefügt werden können, ohne jedes Mal, wenn eine neue Subdomain hinzugefügt wird, die Routing-Regeln neu zu schreiben.

+0

Ich habe bisher nur den eingebauten Visual Studio Server benutzt, also ist die Domain localhost. Ich kann keine subdomain.localhost/was auch immer zu einem gültigen Controller überhaupt noch bekommen. – captncraig

+0

Sie werden nicht mit localhost - um die Domain-Management-Aspekte zu testen, müssen Sie IIS ausführen. – Murph

Antwort

9

MVC ist nicht an die Domäne gebunden, nur an den Pfad (z. B. http://domain/path).

Um dies tun zu können, sollte die folgende benötigen ...

  1. Wildcard DNS-Setup für * .ihredomain.com auf Ihren Server verweist.
  2. Die Website in IIS-Setup mit kein Host-Header. Alle anderen Websites gehostet in dieser Instanz von IIS auf die gleiche IP muss Host-Header angegeben haben.
  3. Ihre Anwendung muss die Anforderung Host Headerentweder beim Laden der Seite, Sitzung starten oder ein anderes Ereignis zu überprüfen.
1

Meistens kein Problem. Ich denke!

In Bezug auf die Anwendung/Routing beginnt das Routing, wo die Domäne endet, so dass mehrere Domänen auf die gleiche Anwendung Mapping ist kein Problem, das wird nur funktionieren.

In Bezug auf IIS können Sie so viele Domänen wie Sie wollen (na ja, es gibt eine Grenze) zu einer einzigen Website zuordnen - ich bin mir nicht sicher, ob Sie einen Platzhalter verwenden können - welche Version von IIS verwenden Sie ?

Wenn eine Anfrage eintrifft, gibt es Ereignisse, die Sie haken können, um die Domäne zu betrachten und somit die gewünschten Parameter einzurichten (Benutzer zum Beispiel), die Stamm-URL für die Anfrage ist auch aus dem Kontext später im Zyklus verfügbar - aber Sie werden es früh aufheben wollen.

Wenn Sie Platzhalter verwenden können, wird es ziemlich trivial - nehmen Sie die Anfrage auf, validieren Sie die Subdomain gegen die Benutzer in der Datenbank (wenn nicht gültig Umleitung auf die Standard-Site), setzen Sie den Benutzer und weiter durch das normale Routing.

Wenn Sie keine Platzhalter verwenden können, fügt die Challenge der IIS-Anwendung (Website) direkt aus Ihrer Anwendung Hostheader hinzu, wenn Benutzer der Datenbank hinzugefügt werden.

+2

Mit IIS, wenn ein Host-Header-Wert für eine Site nicht angegeben ist, akzeptiert es alle Host-Header-Werte, Sie müssen nur sicherstellen, dass Sie nur 1 Website pro IP-Setup in IIS auf diese Weise haben. – MyItchyChin

3

Ich fand eine einfachere Antwort auf dieser Person Blog. Sehr überrascht, dass das so gut funktioniert und dass diese Lösung mehr als 4 Jahre alt ist.

http://blog.maartenballiauw.be/post/2009/05/20/aspnet-mvc-domain-routing.aspx

Eine individuelle Route Implementierung:

public class DomainRoute : Route 
{ 
    public string Domain { get; set; } 


    public override RouteData GetRouteData(HttpContextBase httpContext) 
    { 
     // Build regex 
     domainRegex = CreateRegex(Domain); 
     pathRegex = CreateRegex(Url); 

     // Request information 
     string requestDomain = httpContext.Request.Headers["host"]; 
     if (!string.IsNullOrEmpty(requestDomain)) 
     { 
      if (requestDomain.IndexOf(":") > 0) 
      { 
       requestDomain = requestDomain.Substring(0, requestDomain.IndexOf(":")); 
      } 
     } 
     else 
     { 
      requestDomain = httpContext.Request.Url.Host; 
     } 
     string requestPath = httpContext.Request.AppRelativeCurrentExecutionFilePath.Substring(2) + httpContext.Request.PathInfo; 

     // Match domain and route 
     Match domainMatch = domainRegex.Match(requestDomain); 
     Match pathMatch = pathRegex.Match(requestPath); 

     // Route data 
     RouteData data = null; 
     if (domainMatch.Success && pathMatch.Success) 
     { 
      data = new RouteData(this, RouteHandler); 

      // Add defaults first 
      if (Defaults != null) 
      { 
       foreach (KeyValuePair<string, object> item in Defaults) 
       { 
        data.Values[item.Key] = item.Value; 
       } 
      } 

      // Iterate matching domain groups 
      for (int i = 1; i < domainMatch.Groups.Count; i++) 
      { 
       Group group = domainMatch.Groups[i]; 
       if (group.Success) 
       { 
        string key = domainRegex.GroupNameFromNumber(i); 
        if (!string.IsNullOrEmpty(key) && !char.IsNumber(key, 0)) 
        { 
         if (!string.IsNullOrEmpty(group.Value)) 
         { 
          data.Values[key] = group.Value; 
         } 
        } 
       } 
      } 

      // Iterate matching path groups 
      for (int i = 1; i < pathMatch.Groups.Count; i++) 
      { 
       Group group = pathMatch.Groups[i]; 
       if (group.Success) 
       { 
        string key = pathRegex.GroupNameFromNumber(i); 
        if (!string.IsNullOrEmpty(key) && !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)); 
    } 

    public DomainData GetDomainData(RequestContext requestContext, RouteValueDictionary values) 
    { 
     // Build hostname 
     string hostname = Domain; 
     foreach (KeyValuePair<string, object> pair in values) 
     { 
      hostname = hostname.Replace("{" + pair.Key + "}", pair.Value.ToString()); 
     } 

     // Return domain data 
     return new DomainData 
     { 
      Protocol = "http", 
      HostName = hostname, 
      Fragment = "" 
     }; 
    }} 

Und hier ist, wie es verwendet werden kann.

routes.Add("DomainRoute", new DomainRoute(
"{controller}-{action}.example.com",  // Domain with parameters 
"{id}", // URL with parameters 
new { controller = "Home", action = "Index", id = "" } // Parameter defaults 
)); 
Verwandte Themen