且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

ASP.NET Core 2.0 中基于域的路由

更新时间:2023-02-15 20:48:39

实现此目的的一种方法是制作一个 自定义路由约束 指定每个域名的路由功能.

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

    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);
        }
    }

用法

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?}");
});

请注意,如果您在 Visual Studio 中启动它,它将不适用于标准配置.为了在不更改配置的情况下轻松调试,您可以指定带有域的 URL 作为查询字符串参数:

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

这只是为了让您不必重新配置 IIS 和本地主机文件进行调试(尽管如果您愿意,仍然可以这样做).在 Release 构建期间,此功能被删除,因此它仅适用于生产中的实际域名.

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") }
);