asp.net mvc中的动态子域

时间:2009-11-30 19:49:54

标签: asp.net-mvc iis subdomain

我是asp.net的新手,对iis几乎没有经验。我希望我的应用程序的每个用户都有自己的子域,但都使用相同的控制器。然后子域将控制显示的内容。

示例:

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

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

3 个答案:

答案 0 :(得分:9)

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

要做到这一点,你需要以下......

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

答案 1 :(得分:3)

我在这个人的博客上找到了一个更简单的答案。非常惊讶这个和它一样有效,并且这个解决方案已经超过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
));

答案 2 :(得分:1)

大多不是问题。我想!

就应用程序/路由而言,路由从域结束开始,因此将多个域映射到同一个应用程序不是问题,只会有效。

就IIS而言,您可以根据需要将多个域映射到一个站点 - 我不确定您是否可以使用通配符 - 您使用的是哪个版本的IIS?

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

如果你可以做通配符,它​​变得相当简单 - 接收请求,针对数据库中的用户验证子域(如果无效重定向到默认站点),设置用户并继续正常路由。 / p>

如果你不能做通配符,那么当用户被添加到数据库时,挑战就是从应用程序中动态地向IIS应用程序(网站)添加主机头。