我在Azure网络应用程序中托管了ASP.NET Core 2.0应用程序。
此应用已配置域 domainA.com 。
我的应用中有一条路线,例如 domainA.com/route 。 现在我想将其他域仅限于此路由,例如 domainB.com 。
这样做的最佳方式是什么?
答案 0 :(得分:5)
从ASP.NET Core 3.0开始,并在ASP.NET Core 5.0中提供了持续支持,现在您可以使用新的RequireHost()
扩展方法将单个路由定义限制为特定的主机名,如{{3 }}(与问题标题相反,这并非特定于区域)。
因此,要使@ nightowl888的示例适应已接受的答案,您现在可以在不定义自定义IRouteConstraint
的情况下完成相同的结果:
app.UseMvc(routes =>
{
routes.MapRoute(
name: "DomainA",
template: "route",
defaults: new { controller = "DomainA", action = "Route" }
).RequireHost("domaina.com");
routes.MapRoute(
name: "DomainB",
template: "route",
defaults: new { controller = "DomainB", action = "Route" }
).RequireHost("domainb.com");
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}"
);
});
或者,如果您喜欢在@yanga的方法中使用的属性路由,则现在可以使用新的(但未记录?)Allow routing to areas by hostname:
[Host("domainb.com")]
public DomainController: Controller
{
…
}
显然,这不能解决原始问题,该问题是针对ASP.NET Core 2.0的。但是,由于这是一个未公开的功能,因此我想将其留给试图解决ASP.NET Core 3.0+这个问题的人们使用。
答案 1 :(得分:3)
实现此目的的一种方法是使custom route constraint指定每个域名的路由功能。
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中启动它,它将无法使用标准配置。为了便于在不更改配置的情况下进行调试,您可以将域指定为查询字符串参数:
/route?domain=domaina.com
这样您就不必重新配置IIS和本地主机文件进行调试(尽管您仍然可以这样做)。在Release
版本中,此功能已被删除,因此它仅适用于生产中的实际域名。
由于默认情况下路由会响应所有域名,因此只有在域之间共享大量功能时才能以这种方式执行此操作。如果没有,最好为每个域设置单独的区域:
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") }
);
答案 2 :(得分:3)
对于.net Core MVC,您可以创建一个新的IRouteConstraint和一个RouteAttribute
=> IRouteConstraint.cs
using System;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace Microsoft.AspNetCore.Routing
{
public class ConstraintHost : IRouteConstraint
{
public string _value { get; private set; }
public ConstraintHost(string value)
{
_value = value;
}
public bool Match(HttpContext httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
string hostURL = httpContext.Request.Host.ToString();
if (hostURL == _value)
{
return true;
}
//}
return false;
//return hostURL.IndexOf(_value, StringComparison.OrdinalIgnoreCase) >= 0;
}
public bool Match(HttpContext httpContext, IRouter route, string routeKey, RouteValueDictionary values, RouteDirection routeDirection)
{
throw new NotImplementedException();
}
}
public class ConstraintHostRouteAttribute : RouteAttribute
{
public ConstraintHostRouteAttribute(string template, string sitePermitted)
: base(template)
{
SitePermitted = sitePermitted;
}
public RouteValueDictionary Constraints
{
get
{
var constraints = new RouteValueDictionary();
constraints.Add("host", new ConstraintHost(SitePermitted));
return constraints;
}
}
public string SitePermitted
{
get;
private set;
}
}
}
在您的控制器中可以像这样使用它:
[ConstraintHostRoute("myroute1/xxx", "domaina.com")]
[ConstraintHostRoute("myroute2/yyy", "domainb.com")]
public async Task<ActionResult> MyController()
{
return View();
}