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

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

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


当前回答

如果你正在考虑为你的项目提供多租户功能,为每个租户提供不同的域/子域,你应该看看SaasKit:

https://github.com/saaskit/saaskit

代码示例可以在这里看到:http://benfoster.io/blog/saaskit-multi-tenancy-made-easy

一些使用ASP的例子。NET核心:http://andrewlock.net/forking-the-pipeline-adding-tenant-specific-files-with-saaskit-in-asp-net-core/

编辑: 如果你不想在你的ASP中使用SaasKit。你可以看看Maarten为MVC6实现的域路由:https://blog.maartenballiauw.be/post/2015/02/17/domain-routing-and-resolving-current-tenant-with-aspnet-mvc-6-aspnet-5.html

但是,这些gist没有得到维护,需要对其进行调整,以便与ASP的最新版本一起工作。净的核心。

直接链接到代码:https://gist.github.com/maartenba/77ca6f9cfef50efa96ec#file-domaintemplateroutebuilderextensions-cs

其他回答

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

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

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

如果你正在考虑为你的项目提供多租户功能,为每个租户提供不同的域/子域,你应该看看SaasKit:

https://github.com/saaskit/saaskit

代码示例可以在这里看到:http://benfoster.io/blog/saaskit-multi-tenancy-made-easy

一些使用ASP的例子。NET核心:http://andrewlock.net/forking-the-pipeline-adding-tenant-specific-files-with-saaskit-in-asp-net-core/

编辑: 如果你不想在你的ASP中使用SaasKit。你可以看看Maarten为MVC6实现的域路由:https://blog.maartenballiauw.be/post/2015/02/17/domain-routing-and-resolving-current-tenant-with-aspnet-mvc-6-aspnet-5.html

但是,这些gist没有得到维护,需要对其进行调整,以便与ASP的最新版本一起工作。净的核心。

直接链接到代码:https://gist.github.com/maartenba/77ca6f9cfef50efa96ec#file-domaintemplateroutebuilderextensions-cs

在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();
}

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