Nor*_*isz 7 c# asp.net-core asp.net-core-routing
我在Azure Web应用程序中托管了ASP.NET Core 2.0应用程序。
此应用已配置域domainA.com。
我的应用程序中有一条路由,例如domainA.com/route。现在,我只想将其他域固定到该路由,例如domainB.com。
做这个的最好方式是什么?
对于 .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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
在你的控制器中可以这样使用它:
[ConstraintHostRoute("myroute1/xxx", "domaina.com")]
[ConstraintHostRoute("myroute2/yyy", "domainb.com")]
public async Task<ActionResult> MyController()
{
return View();
}
Run Code Online (Sandbox Code Playgroud)
从 ASP.NET Core 3.0 开始,随着 ASP.NET Core 5.0 和 6.0 的持续支持,您现在可以使用新的RequireHost()扩展方法将单个路由定义限制为特定主机名,如允许通过主机名路由到区域(与问题标题,这不是特定于区域的)。
因此,为了在接受的答案中调整@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?}"
);
});
Run Code Online (Sandbox Code Playgroud)
或者,如果您更喜欢@yanga 方法中使用的属性路由,您现在可以使用新的(但未记录?)HostAttribute:
[Host("domainb.com")]
public DomainController: Controller
{
…
}
Run Code Online (Sandbox Code Playgroud)
显然,这并没有解决最初的问题,即针对 ASP.NET Core 2.0。但是,由于这是一个未(未)记录的功能,因此我想将它留在这里供人们尝试为 ASP.NET Core 3.0+ 解决此问题。
实现此目的的一种方法是创建自定义路由约束,以指定每个域名的路由功能。
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);
}
}
Run Code Online (Sandbox Code Playgroud)
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?}");
});
Run Code Online (Sandbox Code Playgroud)
请注意,如果您在Visual Studio中启动此功能,则无法使用标准配置。为了便于调试而无需更改配置,可以将带有域的URL指定为查询字符串参数:
/route?domain=domaina.com
Run Code Online (Sandbox Code Playgroud)
这样做是为了您不必重新配置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") }
);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2682 次 |
| 最近记录: |