有没有可能有一个ASP。NET MVC路由,使用子域信息来确定它的路由?例如:
user1.domain。例子只有一个 user2.domain。例子指向另一个?
或者,我可以让这两个都去到相同的控制器/动作与用户名参数?
有没有可能有一个ASP。NET MVC路由,使用子域信息来确定它的路由?例如:
user1.domain。例子只有一个 user2.domain。例子指向另一个?
或者,我可以让这两个都去到相同的控制器/动作与用户名参数?
当前回答
你可以通过创建一个新路由并将其添加到global.asax中的RegisterRoutes中的routes集合来实现。下面是一个自定义路由的简单例子:
public class ExampleRoute : RouteBase
{
public override RouteData GetRouteData(HttpContextBase httpContext)
{
var url = httpContext.Request.Headers["HOST"];
var index = url.IndexOf(".");
if (index < 0)
return null;
var subDomain = url.Substring(0, index);
if (subDomain == "user1")
{
var routeData = new RouteData(this, new MvcRouteHandler());
routeData.Values.Add("controller", "User1"); //Goes to the User1Controller class
routeData.Values.Add("action", "Index"); //Goes to the Index action on the User1Controller
return routeData;
}
if (subDomain == "user2")
{
var routeData = new RouteData(this, new MvcRouteHandler());
routeData.Values.Add("controller", "User2"); //Goes to the User2Controller class
routeData.Values.Add("action", "Index"); //Goes to the Index action on the User2Controller
return routeData;
}
return null;
}
public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
//Implement your formating Url formating here
return null;
}
}
其他回答
在ASP。NET Core,主机可以通过Request.Host.Host获得。如果您希望允许通过查询参数覆盖主机,首先检查Request.Query。
要使主机查询参数传播到新的基于路由的url,将以下代码添加到app.UseMvc路由配置中:
routes.Routes.Add(new HostPropagationRouter(routes.DefaultHandler));
然后像这样定义HostPropagationRouter:
/// <summary>
/// A router that propagates the request's "host" query parameter to the response.
/// </summary>
class HostPropagationRouter : IRouter
{
readonly IRouter router;
public HostPropagationRouter(IRouter router)
{
this.router = router;
}
public VirtualPathData GetVirtualPath(VirtualPathContext context)
{
if (context.HttpContext.Request.Query.TryGetValue("host", out var host))
context.Values["host"] = host;
return router.GetVirtualPath(context);
}
public Task RouteAsync(RouteContext context) => router.RouteAsync(context);
}
在定义了一个新的Route处理程序(它将查看URL中传递的主机)之后,您可以使用一个基本控制器的思想,它知道正在访问它的站点。它是这样的:
public abstract class SiteController : Controller {
ISiteProvider _siteProvider;
public SiteController() {
_siteProvider = new SiteProvider();
}
public SiteController(ISiteProvider siteProvider) {
_siteProvider = siteProvider;
}
protected override void Initialize(RequestContext requestContext) {
string[] host = requestContext.HttpContext.Request.Headers["Host"].Split(':');
_siteProvider.Initialise(host[0]);
base.Initialize(requestContext);
}
protected override void OnActionExecuting(ActionExecutingContext filterContext) {
ViewData["Site"] = Site;
base.OnActionExecuting(filterContext);
}
public Site Site {
get {
return _siteProvider.GetCurrentSite();
}
}
}
ISiteProvider是一个简单的接口:
public interface ISiteProvider {
void Initialise(string host);
Site GetCurrentSite();
}
我建议你去卢克·桑普森的博客
是的,但是你必须创建你自己的路由处理器。
通常情况下,路由不知道域,因为应用程序可以部署到任何域,路由不会关心这种或那种方式。但在你的情况下,你想要基于域的控制器和动作,所以你必须创建一个自定义路由,它可以感知域。
几个月前,我开发了一个属性,将方法或控制器限制在特定的域。
它很容易使用:
[IsDomain("localhost","example.com","www.example.com","*.t1.example.com")]
[HttpGet("RestrictedByHost")]
public IActionResult Test(){}
也可以直接应用到控制器上。
public class IsDomainAttribute : Attribute, Microsoft.AspNetCore.Mvc.Filters.IAuthorizationFilter
{
public IsDomainAttribute(params string[] domains)
{
Domains = domains;
}
public string[] Domains { get; }
public void OnAuthorization(AuthorizationFilterContext context)
{
var host = context.HttpContext.Request.Host.Host;
if (Domains.Contains(host))
return;
if (Domains.Any(d => d.EndsWith("*"))
&& Domains.Any(d => host.StartsWith(d.Substring(0, d.Length - 1))))
return;
if (Domains.Any(d => d.StartsWith("*"))
&& Domains.Any(d => host.EndsWith(d.Substring(1))))
return;
context.Result = new Microsoft.AspNetCore.Mvc.NotFoundResult();//.ChallengeResult
}
}
限制: 你可能不能在不同的过滤器的不同方法上有两个相同的路由 我的意思是下面可能会抛出重复路由的异常:
[IsDomain("test1.example.com")]
[HttpGet("/Test")]
public IActionResult Test1(){}
[IsDomain("test2.example.com")]
[HttpGet("/Test")]
public IActionResult Test2(){}
你可以通过创建一个新路由并将其添加到global.asax中的RegisterRoutes中的routes集合来实现。下面是一个自定义路由的简单例子:
public class ExampleRoute : RouteBase
{
public override RouteData GetRouteData(HttpContextBase httpContext)
{
var url = httpContext.Request.Headers["HOST"];
var index = url.IndexOf(".");
if (index < 0)
return null;
var subDomain = url.Substring(0, index);
if (subDomain == "user1")
{
var routeData = new RouteData(this, new MvcRouteHandler());
routeData.Values.Add("controller", "User1"); //Goes to the User1Controller class
routeData.Values.Add("action", "Index"); //Goes to the Index action on the User1Controller
return routeData;
}
if (subDomain == "user2")
{
var routeData = new RouteData(this, new MvcRouteHandler());
routeData.Values.Add("controller", "User2"); //Goes to the User2Controller class
routeData.Values.Add("action", "Index"); //Goes to the Index action on the User2Controller
return routeData;
}
return null;
}
public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
//Implement your formating Url formating here
return null;
}
}