Динамические субдомены в asp.net mvc - PullRequest
10 голосов
/ 30 ноября 2009

Я довольно новичок в asp.net, и у меня мало опыта работы с iis. Я бы хотел, чтобы каждый пользователь моего приложения получил свой собственный поддомен, но все они использовали одни и те же контроллеры. Затем поддомен будет контролировать, какой контент отображается.

Пример:

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

Оба будут использовать один и тот же контроллер. В идеале параметр мог бы дать имя пользователя контроллеру, который затем мог бы отображать соответствующий контент. Мне бы хотелось, чтобы он был достаточно гибким, чтобы новые субдомены можно было добавлять в базу данных без переписывания правил маршрутизации при каждом добавлении нового субдомена.

Ответы [ 3 ]

9 голосов
/ 30 ноября 2009

MVC не привязан к домену, только к пути (например, http://domain/path).

Чтобы сделать это правильно, вам нужно следующее ...

  1. Подстановочный знак DNS для * .yourdomain.com указывает на ваш сервер.
  2. Сайт в настройках IIS с Нет заголовка хоста. Любые другие сайты размещенный в этом экземпляре IIS на один и тот же IP-адрес должен иметь заголовки хоста указано.
  3. Ваша заявка должна будет проверить запросить заголовок хоста при загрузке страницы, начало сеанса или другое событие.
3 голосов
/ 12 октября 2013

Я нашел более простой ответ в блоге этого человека. Очень удивлен, что это работает так же хорошо, как и что этому решению более 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
));
1 голос
/ 30 ноября 2009

В основном не проблема. Я думаю!

С точки зрения приложения / маршрутизации маршрутизация начинается там, где заканчивается домен, поэтому сопоставление нескольких доменов одному приложению не является проблемой, это просто сработает.

С точки зрения IIS вы можете сопоставить столько доменов, сколько вы хотите (ну, конечно, существует ограничение) на один сайт - я не уверен, что вы можете использовать подстановочный знак - какую версию IIS вы используете?

Когда приходит запрос, есть события, которые вы можете подключить, чтобы посмотреть на домен и, следовательно, настроить нужные параметры (например, для пользователя), корневой URL-адрес для запроса будет доступен из контекста и позже в этом цикле - но вы Я хочу забрать его пораньше.

Если вы можете использовать подстановочные знаки, это становится довольно тривиальным - забрать запрос, проверить поддомен по отношению к пользователям в базе данных (если недопустимое перенаправление на сайт по умолчанию), настроить пользователя и продолжить обычную маршрутизацию.

Если вы не можете использовать подстановочные знаки, тогда проблема заключается в добавлении заголовков узлов в приложение IIS (веб-сайт) на лету из вашего приложения по мере добавления пользователей в базу данных.

...