域通常不是路由的一部分,这就是您的示例不起作用的原因。要使路由仅适用于特定域,您必须自定义路由。
默认情况下,您的路由配置中的所有路由都将在可以访问该网站的所有域上可用。
对此最简单的解决方案是创建一个custom route constraint 并使用它来控制特定 URL 将匹配的域。
域约束
public class DomainConstraint : IRouteConstraint
{
private readonly string[] domains;
public DomainConstraint(params string[] domains)
{
this.domains = domains ?? throw new ArgumentNullException(nameof(domains));
}
public bool Match(HttpContextBase httpContext, Route route, string parameterName, 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.QueryString["domain"];
#else
null;
#endif
if (string.IsNullOrEmpty(domain))
domain = httpContext.Request.Headers["HOST"];
return domains.Contains(domain);
}
}
用法
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
// This ignores Category/Cars for www.domain.com and www.foo.com
routes.IgnoreRoute("Category/Cars", new { _ = new DomainConstraint("www.domain.com", "www.foo.com") });
// Matches www.domain2.com/ and sends it to CategoryController.Cars
routes.MapRoute(
name: "HomePageDomain2",
url: "",
defaults: new { controller = "Category", action = "Cars" },
constraints: new { _ = new DomainConstraint("www.domain2.com") }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
// This constraint allows the route to work either
// on "www.domain.com" or "www.domain2.com" (excluding any other domain)
constraints: new { _ = new DomainConstraint("www.domain.com", "www.domain2.com") }
);
}
}
如果您在 Visual Studio 的新项目中启动它,您会注意到它显示错误。这是因为localhost:<port> 不是已配置的域。但是,如果您导航到:
/?domain=www.domain.com
您将看到主页。
这是因为仅对于调试版本,它允许您覆盖“本地”域名以进行测试。您可以configure your local IIS server 使用本地静态IP 地址(添加到您的网卡)并添加本地主机文件条目以在本地测试它没有查询字符串参数。
请注意,在进行“发布”构建时,无法使用查询字符串参数进行测试,因为这会带来潜在的安全漏洞。
如果您使用网址:
/?domain=www.domain2.com
它将运行CategoryController.Cars 操作方法(如果存在)。
请注意,由于Default 路由涵盖了范围广泛的 URL,因此大部分站点将可供www.domain.com 和www.domain2.com 使用。例如,您可以在以下位置访问“关于”页面:
/Home/About?domain=www.domain.com
/Home/About?domain=www.domain2.com
您可以使用IgnoreRoute extension method 来阻止您不想要的 URL(它接受路由约束,因此该解决方案也可以在那里工作)。
如果您主要希望在域之间共享功能,此解决方案将起作用。如果您希望在一个网站中有 2 个域,但让它们像单独的网站一样,则如果您使用上述路由约束为项目中的每个“网站”使用 Area 会更容易管理区域路线。
public class Domain2AreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "Domain2";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
name: "Domain2_default",
url: "{controller}/{action}/{id}",
defaults: new { action = "Index", id = UrlParameter.Optional },
constraints: new { _ = DomainConstraint("www.domain2.com") }
);
}
}
上述配置将使www.domain2.com 的每个 URL(即 0、1、2 或 3 段长)路由到 Domain2 区域中的控制器。