asp.net mvc 中的动态子域

发布于 2024-08-13 08:34:04 字数 294 浏览 4 评论 0原文

我对 ASP.NET 相当陌生,对 IIS 也没什么经验。我想让我的应用程序的每个用户都有自己的子域,但都使用相同的控制器。然后子域将控制显示的内容。

示例:

user1subdomain.mydomain.com/Whatever
user2subdomain.mydomain.com/Whatever

两者将使用相同的控制器。理想情况下,参数可以将用户名提供给控制器,然后控制器可以显示适当的内容。我希望它足够灵活,可以将新的子域添加到数据库中,而无需每次添加新子域时都重写路由规则。

I am fairly new to asp.net, and have little experience with iis. I would like to have each user of my application get their own sub-domain, but all use the same controllers. The subdomain would then control what content is displayed.

Example:

user1subdomain.mydomain.com/Whatever
user2subdomain.mydomain.com/Whatever

Will both use the same controller. Ideally a parameter could give the user name to the controller, which could then display the appropriate content. I would like it to be flexible enough that new subdomains could be added to the database without rewriting routing rules every time a new subdomain is added.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

江城子 2024-08-20 08:34:04

MVC 不绑定到域,只绑定到路径(例如 http://domain/path)。

要正确执行此操作,您需要以下...

  1. 通配符 DNS 设置
    *.yourdomain.com 指向您的服务器。
  2. IIS 设置中的站点
    没有主机头。任何其他网站
    托管在该 IIS 实例中
    相同的IP必须有Host头
    指定的。
  3. 您的申请需要检查
    在页面加载时请求主机标头,
    会话开始或其他一些事件。

MVC is not bound to the domain, just to the path (e.g. http://domain/path).

To do this properly you need the following...

  1. Wildcard DNS setup for
    *.yourdomain.com pointing to your server.
  2. The site in IIS setup with
    no Host Header. Any other sites
    hosted in that instance of IIS on
    the same IP must have Host headers
    specified.
  3. Your application will need to check the
    request host header either on page load,
    session start or some other event.
违心° 2024-08-20 08:34:04

我在这个人的博客上找到了一个更简单的答案。非常令人惊讶的是,它的效果如此之好,而且这个解决方案已有 4 年多的历史了。

http://blog.maartenballiauw.be/post /2009/05/20/aspnet-mvc-domain-routing.aspx

自定义路由实现:

public class DomainRoute : Route
{
    public string Domain { get; set; }


    public override RouteData GetRouteData(HttpContextBase httpContext)
    {
        // Build regex
        domainRegex = CreateRegex(Domain);
        pathRegex = CreateRegex(Url);

        // Request information
        string requestDomain = httpContext.Request.Headers["host"];
        if (!string.IsNullOrEmpty(requestDomain))
        {
            if (requestDomain.IndexOf(":") > 0)
            {
                requestDomain = requestDomain.Substring(0, requestDomain.IndexOf(":"));
            }
        }
        else
        {
            requestDomain = httpContext.Request.Url.Host;
        }
        string requestPath = httpContext.Request.AppRelativeCurrentExecutionFilePath.Substring(2) + httpContext.Request.PathInfo;

        // Match domain and route
        Match domainMatch = domainRegex.Match(requestDomain);
        Match pathMatch = pathRegex.Match(requestPath);

        // Route data
        RouteData data = null;
        if (domainMatch.Success && pathMatch.Success)
        {
            data = new RouteData(this, RouteHandler);

            // Add defaults first
            if (Defaults != null)
            {
                foreach (KeyValuePair<string, object> item in Defaults)
                {
                    data.Values[item.Key] = item.Value;
                }
            }

            // Iterate matching domain groups
            for (int i = 1; i < domainMatch.Groups.Count; i++)
            {
                Group group = domainMatch.Groups[i];
                if (group.Success)
                {
                    string key = domainRegex.GroupNameFromNumber(i);
                    if (!string.IsNullOrEmpty(key) && !char.IsNumber(key, 0))
                    {
                        if (!string.IsNullOrEmpty(group.Value))
                        {
                            data.Values[key] = group.Value;
                        }
                    }
                }
            }

            // Iterate matching path groups
            for (int i = 1; i < pathMatch.Groups.Count; i++)
            {
                Group group = pathMatch.Groups[i];
                if (group.Success)
                {
                    string key = pathRegex.GroupNameFromNumber(i);
                    if (!string.IsNullOrEmpty(key) && !char.IsNumber(key, 0))
                    {
                        if (!string.IsNullOrEmpty(group.Value))
                        {
                            data.Values[key] = group.Value;
                        }
                    }
                }
            }
        }    
    return data;
    }

    public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
    {
        return base.GetVirtualPath(requestContext, RemoveDomainTokens(values));
    }

    public DomainData GetDomainData(RequestContext requestContext, RouteValueDictionary values)
    {
        // Build hostname
        string hostname = Domain;
        foreach (KeyValuePair<string, object> pair in values)
        {
            hostname = hostname.Replace("{" + pair.Key + "}", pair.Value.ToString());
        }

        // Return domain data
        return new DomainData
        {
            Protocol = "http",
            HostName = hostname,
            Fragment = ""
        };
    }}

以下是它的使用方法。

routes.Add("DomainRoute", new DomainRoute(
"{controller}-{action}.example.com",     // Domain with parameters
"{id}",    // URL with parameters
new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
));

I found an easier answer on this person's blog. Very surprised this works as well as it does and that this solution is more than 4 years old.

http://blog.maartenballiauw.be/post/2009/05/20/aspnet-mvc-domain-routing.aspx

A custom route implementation:

public class DomainRoute : Route
{
    public string Domain { get; set; }


    public override RouteData GetRouteData(HttpContextBase httpContext)
    {
        // Build regex
        domainRegex = CreateRegex(Domain);
        pathRegex = CreateRegex(Url);

        // Request information
        string requestDomain = httpContext.Request.Headers["host"];
        if (!string.IsNullOrEmpty(requestDomain))
        {
            if (requestDomain.IndexOf(":") > 0)
            {
                requestDomain = requestDomain.Substring(0, requestDomain.IndexOf(":"));
            }
        }
        else
        {
            requestDomain = httpContext.Request.Url.Host;
        }
        string requestPath = httpContext.Request.AppRelativeCurrentExecutionFilePath.Substring(2) + httpContext.Request.PathInfo;

        // Match domain and route
        Match domainMatch = domainRegex.Match(requestDomain);
        Match pathMatch = pathRegex.Match(requestPath);

        // Route data
        RouteData data = null;
        if (domainMatch.Success && pathMatch.Success)
        {
            data = new RouteData(this, RouteHandler);

            // Add defaults first
            if (Defaults != null)
            {
                foreach (KeyValuePair<string, object> item in Defaults)
                {
                    data.Values[item.Key] = item.Value;
                }
            }

            // Iterate matching domain groups
            for (int i = 1; i < domainMatch.Groups.Count; i++)
            {
                Group group = domainMatch.Groups[i];
                if (group.Success)
                {
                    string key = domainRegex.GroupNameFromNumber(i);
                    if (!string.IsNullOrEmpty(key) && !char.IsNumber(key, 0))
                    {
                        if (!string.IsNullOrEmpty(group.Value))
                        {
                            data.Values[key] = group.Value;
                        }
                    }
                }
            }

            // Iterate matching path groups
            for (int i = 1; i < pathMatch.Groups.Count; i++)
            {
                Group group = pathMatch.Groups[i];
                if (group.Success)
                {
                    string key = pathRegex.GroupNameFromNumber(i);
                    if (!string.IsNullOrEmpty(key) && !char.IsNumber(key, 0))
                    {
                        if (!string.IsNullOrEmpty(group.Value))
                        {
                            data.Values[key] = group.Value;
                        }
                    }
                }
            }
        }    
    return data;
    }

    public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
    {
        return base.GetVirtualPath(requestContext, RemoveDomainTokens(values));
    }

    public DomainData GetDomainData(RequestContext requestContext, RouteValueDictionary values)
    {
        // Build hostname
        string hostname = Domain;
        foreach (KeyValuePair<string, object> pair in values)
        {
            hostname = hostname.Replace("{" + pair.Key + "}", pair.Value.ToString());
        }

        // Return domain data
        return new DomainData
        {
            Protocol = "http",
            HostName = hostname,
            Fragment = ""
        };
    }}

And here is how it can be used.

routes.Add("DomainRoute", new DomainRoute(
"{controller}-{action}.example.com",     // Domain with parameters
"{id}",    // URL with parameters
new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
));
泅人 2024-08-20 08:34:04

大部分都不是问题。我认为!

就应用程序/路由而言,路由从域结束的地方开始,因此将多个域映射到同一应用程序不是问题,这会起作用。

就 IIS 而言,您可以将任意数量的域(当然肯定有限制)映射到单个站点 - 我不确定您是否可以使用通配符 - 您使用的是哪个版本的 IIS?

当请求到达时,您可以挂钩一些事件来查看域,从而设置您想要的参数(例如用户),请求的根 URL 也可以在周期的稍后上下文中获得 - 但您需要尽早拿起它。

如果您可以使用通配符,那么它就变得相当简单 - 获取请求,根据数据库中的用户验证子域(如果没有有效重定向到默认站点),设置用户并继续正常路由。

如果您无法使用通配符,那么挑战就是在将用户添加到数据库时,从您的应用程序动态地将主机标头添加到 IIS 应用程序(网站)。

Mostly not a problem. I think!

In terms of the application/routing the routing starts where the domain ends so mapping multiple domains to the same application is not a problem, that will just work.

In terms of IIS you can map as many domains as you want (well there's bound to be a limit) to a single site - I'm not sure if you can use a wildcard - what version of IIS are you using?

When a request arrives there are events you can hook to look at the domain and hence set up parameters you want (user for example), the root URL for the request is available from the context later in the cycle too - but you'll want to pick it up early.

If you can do wildcards it becomes fairly trivial - pick up the request, validate the subdomain against the users in the database (if not valid redirect to the default site), set the user and carry on through the normal routing.

If you can't do wildcards then the challenge is adding host headers to the IIS application (website) on the fly from your application as users are added to the database.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文