Domain-based routing in ASP.NET Core 2.0

后端 未结 3 1847
梦如初夏
梦如初夏 2020-12-03 04:27

I have an ASP.NET Core 2.0 app hosted on an Azure App Service.

This application is bound to domainA.com. I have one route in my app—for example, d

3条回答
  •  广开言路
    2020-12-03 04:51

    One way to accomplish this is to make a custom route constraint to specify which routes function for each domain name.

    DomainConstraint

        public class DomainConstraint : IRouteConstraint
        {
            private readonly string[] domains;
    
            public DomainConstraint(params string[] domains)
            {
                this.domains = domains ?? throw new ArgumentNullException(nameof(domains));
            }
    
            public bool Match(HttpContext httpContext, IRouter route, string routeKey, RouteValueDictionary values, RouteDirection routeDirection)
            {
                string domain =
    #if DEBUG
                    // A domain specified as a query parameter takes precedence 
                    // over the hostname (in debug compile only).
                    // This allows for testing without configuring IIS with a 
                    // static IP or editing the local hosts file.
                    httpContext.Request.Query["domain"];
    #else
                    null;
    #endif
                if (string.IsNullOrEmpty(domain))
                    domain = httpContext.Request.Host.Host;
    
                return domains.Contains(domain);
            }
        }
    

    Usage

    app.UseMvc(routes =>
    {
        routes.MapRoute(
            name: "DomainA",
            template: "route",
            defaults: new { controller = "DomainA", action = "Route" },
            constraints: new { _ = new DomainConstraint("domaina.com") });
    
        routes.MapRoute(
            name: "DomainB",
            template: "route",
            defaults: new { controller = "DomainB", action = "Route" },
            constraints: new { _ = new DomainConstraint("domainb.com") });
    
        routes.MapRoute(
            name: "default",
            template: "{controller=Home}/{action=Index}/{id?}");
    });
    

    Note that if you fire this up in Visual Studio it won't work with the standard configuration. To allow for easy debugging without changing the configuration, you can specify the URL with the domain as a query string parameter:

    /route?domain=domaina.com
    

    This is just so you don't have to reconfigure IIS and your local hosts file to debug (although you still can if you prefer that way). During a Release build this feature is removed so it will only work with the actual domain name in production.

    Since routes respond to all domain names by default, it only makes sense to do it this way if you have a large amount of functionality that is shared between domains. If not, it is better to setup separate areas for each domain:

    routes.MapRoute(
        name: "DomainA",
        template: "{controller=Home}/{action=Index}/{id?}",
        defaults: new { area = "DomainA" },
        constraints: new { _ = new DomainConstraint("domaina.com") }
    );
    
    routes.MapRoute(
        name: "DomainA",
        template: "{controller=Home}/{action=Index}/{id?}",
        defaults: new { area = "DomainB" },
        constraints: new { _ = new DomainConstraint("domainb.com") }
    );
    

提交回复
热议问题