有没有可能有一个ASP。NET MVC路由,使用子域信息来确定它的路由?例如:

user1.domain。例子只有一个 user2.domain。例子指向另一个?

或者,我可以让这两个都去到相同的控制器/动作与用户名参数?


当前回答

在定义了一个新的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(){}

在定义了一个新的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();
}

我建议你去卢克·桑普森的博客

是的,但是你必须创建你自己的路由处理器。

通常情况下,路由不知道域,因为应用程序可以部署到任何域,路由不会关心这种或那种方式。但在你的情况下,你想要基于域的控制器和动作,所以你必须创建一个自定义路由,它可以感知域。

你可以通过创建一个新路由并将其添加到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;
    }
}

我创建了子域路由库,您可以创建这样的路由。它目前正在为。net Core 1.1和。net Framework 4.6.1工作,但将在不久的将来进行更新。它是这样工作的: 1)在Startup.cs中映射子域路由

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    var hostnames = new[] { "localhost:54575" };

    app.UseMvc(routes =>
    {
        routes.MapSubdomainRoute(
            hostnames,
            "SubdomainRoute",
            "{username}",
            "{controller}/{action}",
            new { controller = "Home", action = "Index" });
    )};

2)控制器/ HomeController.cs

public IActionResult Index(string username)
{
    //code
}

3)该库还将允许您生成url和表单。代码:

@Html.ActionLink("User home", "Index", "Home" new { username = "user1" }, null)

将生成<a href="http://user1。localhost: 54575 / Home /指数”> < / >用户家里 生成的URL还取决于当前主机位置和模式。 你也可以为BeginForm和UrlHelper使用html帮助。如果你喜欢,你也可以使用新功能称为标签助手(FormTagHelper, AnchorTagHelper) 该库还没有任何文档,但有一些测试和示例项目,所以请随意探索。