Frage

Ist es möglich, eine ASP.NET MVC Route zu haben, die Sub-Domain Informationen verwendet, um seine Route zu bestimmen? Zum Beispiel:

  • user1 .domain.com geht an einen Ort
  • benutzer2 .domain.com geht zum anderen?

Oder kann ich es so diese beide machen gehe auf die gleiche Controller / Aktion mit einem username Parameter?

War es hilfreich?

Lösung

Sie können es tun, indem Sie einen neuen Weg zu schaffen und an die Routen-Sammlung in RegisterRoutes in Ihrer global.asax hinzufügen. Unten ist ein sehr einfaches Beispiel für eine benutzerdefinierte Route:

public class ExampleRoute : RouteBase
{

    public override RouteData GetRouteData(HttpContextBase httpContext)
    {
        var url = httpContext.Request.Headers["HOST"];
        var index = url.IndexOf(".");

        if (index < 0)
            return null;

        var subDomain = url.Substring(0, index);

        if (subDomain == "user1")
        {
            var routeData = new RouteData(this, new MvcRouteHandler());
            routeData.Values.Add("controller", "User1"); //Goes to the User1Controller class
            routeData.Values.Add("action", "Index"); //Goes to the Index action on the User1Controller

            return routeData;
        }

        if (subDomain == "user2")
        {
            var routeData = new RouteData(this, new MvcRouteHandler());
            routeData.Values.Add("controller", "User2"); //Goes to the User2Controller class
            routeData.Values.Add("action", "Index"); //Goes to the Index action on the User2Controller

            return routeData;
        }

        return null;
    }

    public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
    {
        //Implement your formating Url formating here
        return null;
    }
}

Andere Tipps

die Sub-Domain erfassen, während der Standard-MVC5 Routing-Funktionen beibehalten , verwenden Sie die folgende SubdomainRoute Klasse von Route abgeleitet.

Darüber hinaus ermöglicht SubdomainRoute die Sub-Domain optional als Abfrage-Parameter angegeben werden, sub.example.com/foo/bar und example.com/foo/bar?subdomain=sub gleichwertig zu machen. Auf diese Weise können Sie testen, bevor die DNS-Unterdomänen konfiguriert sind. Die Abfrage-Parameter (bei Gebrauch) durch neue Links von Url.Action erzeugt propagiert wird, etc.

Die Abfrage-Parameter ermöglichen auch lokale Debuggen mit Visual Studio 2013 ohne href="https://stackoverflow.com/a/14967651/145173"> mit netsh konfigurieren, um laufen. In der Standardeinstellung IIS Express bindet nur an localhost , wenn nicht erhöht; es wird nicht binden auch Host-Namen wie sub.localtest.me .

class SubdomainRoute : Route
{
    public SubdomainRoute(string url) : base(url, new MvcRouteHandler()) {}

    public override RouteData GetRouteData(HttpContextBase httpContext)
    {
        var routeData = base.GetRouteData(httpContext);
        if (routeData == null) return null; // Only look at the subdomain if this route matches in the first place.
        string subdomain = httpContext.Request.Params["subdomain"]; // A subdomain specified as a query parameter takes precedence over the hostname.
        if (subdomain == null) {
            string host = httpContext.Request.Headers["Host"];
            int index = host.IndexOf('.');
            if (index >= 0)
                subdomain = host.Substring(0, index);
        }
        if (subdomain != null)
            routeData.Values["subdomain"] = subdomain;
        return routeData;
    }

    public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
    {
        object subdomainParam = requestContext.HttpContext.Request.Params["subdomain"];
        if (subdomainParam != null)
            values["subdomain"] = subdomainParam;
        return base.GetVirtualPath(requestContext, values);
    }
}

Der Einfachheit halber, rufen Sie die folgende MapSubdomainRoute Methode von Ihrem RegisterRoutes Methode so wie man es nur alte MapRoute:

static void MapSubdomainRoute(this RouteCollection routes, string name, string url, object defaults = null, object constraints = null)
{
    routes.Add(name, new SubdomainRoute(url) {
        Defaults = new RouteValueDictionary(defaults),
        Constraints = new RouteValueDictionary(constraints),
        DataTokens = new RouteValueDictionary()
    });
}

Schließlich, um bequem die Sub-Domain zuzugreifen (entweder von einer echten Sub-Domain oder einem Abfrage-Parametern), ist es hilfreich, eine Controller-Basisklasse mit dieser Subdomain Eigenschaft zu erstellen:

protected string Subdomain
{
    get { return (string)Request.RequestContext.RouteData.Values["subdomain"]; }
}

Das ist nicht meine Arbeit, aber ich hatte es zu dieser Antwort hinzuzufügen.

Hier ist eine großartige Lösung für dieses Problem. Maartin Balliauw schrieb Code, der eine DomainRoute Klasse erstellt, die sehr ähnlich zu dem normalen Routing verwendet werden können.

http: //blog.maartenballiauw. sein / Post / 2009/05/20 / ASPNET-MVC-Domain-Routing.aspx

Beispiel Verwendung so sein würde ...

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

;

die Sub-Domain zu erfassen, wenn mit Web API , die Aktionsauswahl außer Kraft setzt einen subdomain Abfrageparameter zu injizieren. Dann nutzen Sie die Sub-Domain-Abfrage-Parameter in Ihre Controller Aktionen wie folgt aus:

public string Get(string id, string subdomain)

Dieser Ansatz macht das Debuggen praktisch, da Sie die Abfrage-Parameter von Hand angeben können bei der Verwendung von localhost anstelle des tatsächlichen Hostnamen (siehe Standard MVC5 Routing-Antwort für Details). Dies ist der Code für die Aktion Selector:

class SubdomainActionSelector : IHttpActionSelector
{
    private readonly IHttpActionSelector defaultSelector;

    public SubdomainActionSelector(IHttpActionSelector defaultSelector)
    {
        this.defaultSelector = defaultSelector;
    }

    public ILookup<string, HttpActionDescriptor> GetActionMapping(HttpControllerDescriptor controllerDescriptor)
    {
        return defaultSelector.GetActionMapping(controllerDescriptor);
    }

    public HttpActionDescriptor SelectAction(HttpControllerContext controllerContext)
    {
        var routeValues = controllerContext.Request.GetRouteData().Values;
        if (!routeValues.ContainsKey("subdomain")) {
            string host = controllerContext.Request.Headers.Host;
            int index = host.IndexOf('.');
            if (index >= 0)
                controllerContext.Request.GetRouteData().Values.Add("subdomain", host.Substring(0, index));
        }
        return defaultSelector.SelectAction(controllerContext);
    }
}

Ersetzen Sie den Standard Aktion Selector durch das Hinzufügen dieser zu WebApiConfig.Register:

config.Services.Replace(typeof(IHttpActionSelector), new SubdomainActionSelector(config.Services.GetActionSelector()));

Ja, aber Sie haben Ihre eigenen Route-Handler zu erstellen.

Normalerweise ist der Weg der Domäne nicht bekannt, da die Anwendung für alle Domain eingesetzt werden könnte und der Weg wäre eine oder andere Weise nicht. Aber in Ihrem Fall, dass Sie den Controller und die Aktion aus der Domäne stützen, so dass Sie eine benutzerdefinierte Route erstellen müssen, die sich die Domäne ist.

Ich habe Bibliothek für Sub-Domain Routing, die Sie so eine Route erstellen können. Es arbeitet derzeit für ein .NET-Core 1.1 und .NET Framework 4.6.1 wird aber in naher Zukunft aktualisiert werden. Dies ist, wie es funktioniert:
1) Karte Sub-Domain-Route in Startup.cs

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    var hostnames = new[] { "localhost:54575" };

    app.UseMvc(routes =>
    {
        routes.MapSubdomainRoute(
            hostnames,
            "SubdomainRoute",
            "{username}",
            "{controller}/{action}",
            new { controller = "Home", action = "Index" });
    )};

2) Controller / HomeController.cs

public IActionResult Index(string username)
{
    //code
}

3) Das lib ermöglicht es Ihnen, auch URLs und Formen zu erzeugen. Code:

@Html.ActionLink("User home", "Index", "Home" new { username = "user1" }, null)

Wird <a href="http://user1.localhost:54575/Home/Index">User home</a> erzeugen Erzeugte URL hängt auch von aktuellen Host-Standort und Schema.
Sie können auch HTML-Helfer für BeginForm und UrlHelper verwenden. Wenn Sie möchten, können Sie auch neue Funktion namens Tag Helfer (FormTagHelper, AnchorTagHelper) verwenden
Das lib hat keine Dokumentation noch nicht, aber es gibt einige Tests und Proben projizieren, so fühlen sich frei, es zu entdecken.

ASP.NET-Core , die Host über Request.Host.Host zur Verfügung steht. Wenn Sie den Host über einen Abfrageparameter, erste Prüfung Request.Query ermöglichen überschrieben.

Um einen Host-Abfrage-Parameter führen zu neuer Route-basierte URLs propagieren in diesen Code zur Konfiguration app.UseMvc Route hinzufügen:

routes.Routes.Add(new HostPropagationRouter(routes.DefaultHandler));

Und definieren HostPropagationRouter wie folgt aus:

/// <summary>
/// A router that propagates the request's "host" query parameter to the response.
/// </summary>
class HostPropagationRouter : IRouter
{
    readonly IRouter router;

    public HostPropagationRouter(IRouter router)
    {
        this.router = router;
    }

    public VirtualPathData GetVirtualPath(VirtualPathContext context)
    {
        if (context.HttpContext.Request.Query.TryGetValue("host", out var host))
            context.Values["host"] = host;
        return router.GetVirtualPath(context);
    }

    public Task RouteAsync(RouteContext context) => router.RouteAsync(context);
}

Nach einem neuen Route-Handler definiert, die auf dem Host in der URL übergab aussehen würden, können Sie mit der Idee eines Basis-Controller gehen, die Kenntnis von der Seite ist es für zugegriffen werden wird. Es sieht wie folgt aus:

public abstract class SiteController : Controller {
    ISiteProvider _siteProvider;

    public SiteController() {
        _siteProvider = new SiteProvider();
    }

    public SiteController(ISiteProvider siteProvider) {
        _siteProvider = siteProvider;
    }

    protected override void Initialize(RequestContext requestContext) {
        string[] host = requestContext.HttpContext.Request.Headers["Host"].Split(':');

        _siteProvider.Initialise(host[0]);

        base.Initialize(requestContext);
    }

    protected override void OnActionExecuting(ActionExecutingContext filterContext) {
        ViewData["Site"] = Site;

        base.OnActionExecuting(filterContext);
    }

    public Site Site {
        get {
            return _siteProvider.GetCurrentSite();
        }
    }

}

ISiteProvider ist eine einfache Schnittstelle:

public interface ISiteProvider {
    void Initialise(string host);
    Site GetCurrentSite();
}

Ich verweise Sie gehen href="http://blog.lukesampson.com/subdomains-for-a-single-application-with-asp-net-mvc" zum Luke Sampson Blog

Wenn Sie gibt Multitenancy Fähigkeiten zu einem Projekt mit unterschiedlichen Domains / Subdomains für jeden Mieter suchen, sollten Sie einen Blick auf SaasKit haben:

https://github.com/saaskit/saaskit

Code-Beispiele hier zu sehen ist: http://benfoster.io/blog / saaskit-Multi-Tenancy-made-easy

Einige Beispiele mit ASP.NET Kern: http://andrewlock.net/forking-the-pipeline-adding-tenant-specific-files-with-saaskit-in-asp-net-core/

EDIT: Wenn Sie nicht wollen tun SaasKit in ASP.NET-Kernprojekt verwenden, können Sie einen Blick auf Maarten Implementierung von Domain-Routing für MVC6 haben: https://blog.maartenballiauw.be/post/2015/02/ 17 / Domain-Routing-and-Auflösungsstrom-Tenant-with-aspnet-MVC-6-aspnet-5.html

Doch diese Gists nicht gehalten werden und müssen optimiert werden mit der neuesten Version von ASP.NET Kern zu arbeiten.

Direktlink zum Code: https://gist.github.com/ maartenba / 77ca6f9cfef50efa96ec # file-domaintemplateroutebuilderextensions-cs

Ein paar Monate vor habe ich ein Attribut entwickelt, die Methoden oder Controller auf bestimmte Domänen beschränkt.

Es ist ganz einfach zu bedienen:

[IsDomain("localhost","example.com","www.example.com","*.t1.example.com")]
[HttpGet("RestrictedByHost")]
public IActionResult Test(){}

Sie können auch auf einem Controller gelten direkt an.

public class IsDomainAttribute : Attribute, Microsoft.AspNetCore.Mvc.Filters.IAuthorizationFilter
{

    public IsDomainAttribute(params string[]  domains)
    {
        Domains = domains;
    }

    public string[] Domains { get; }

    public void OnAuthorization(AuthorizationFilterContext context)
    {
        var host = context.HttpContext.Request.Host.Host;
        if (Domains.Contains(host))
            return;
        if (Domains.Any(d => d.EndsWith("*"))
                && Domains.Any(d => host.StartsWith(d.Substring(0, d.Length - 1))))
            return;
        if (Domains.Any(d => d.StartsWith("*"))
                && Domains.Any(d => host.EndsWith(d.Substring(1))))
            return;

        context.Result = new Microsoft.AspNetCore.Mvc.NotFoundResult();//.ChallengeResult
    }
}

Einschränkung: Sie kann in der Lage zu zwei gleichen Strecken auf unterschiedlichen Methoden mit unterschiedlichen Filtern nicht Ich meine die folgende möglicherweise eine Ausnahme für doppelte Strecke werfen:

[IsDomain("test1.example.com")]
[HttpGet("/Test")]
public IActionResult Test1(){}

[IsDomain("test2.example.com")]
[HttpGet("/Test")]
public IActionResult Test2(){}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top