Динамические поддомены в asp.net mvc
Я новичок в asp.net, и у меня мало опыта работы с iis. Я хотел бы, чтобы каждый пользователь моего приложения получал свой собственный поддомен, но все используют одни и те же контроллеры. Затем субдомен будет контролировать, какой контент отображается.
Пример:
user1subdomain.mydomain.com/Whatever
user2subdomain.mydomain.com/Whatever
Оба будут использовать один и тот же контроллер. В идеале параметр может дать имя пользователя контроллеру, который затем может отображать соответствующий контент. Я бы хотел, чтобы он был достаточно гибким, чтобы новые поддомены могли быть добавлены в базу данных, не переписывая правила маршрутизации каждый раз, когда добавляется новый субдомен.
Ответы
Ответ 1
MVC не привязан к домену, только к пути (например, http://domain/path).
Чтобы сделать это правильно, вам понадобится следующее...
- Настройка подстановочных DNS для
*.yourdomain.com, указывающий на ваш сервер.
- Сайт в настройке IIS с
нет заголовка хоста. Любые другие сайты
размещенный в этом экземпляре IIS
тот же IP должен иметь заголовки хоста
указано.
- Ваше приложение должно будет проверить
запросить заголовок хоста либо на загрузке страницы,
запуск сеанса или другое событие.
Ответ 2
Я нашел более легкий ответ в этом человеческом блоге. Очень удивляет, что это работает так же хорошо, как и делает, и что это решение более 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
));
Ответ 3
В основном не проблема. Я думаю!
В терминах приложения/маршрутизации маршрутизация начинается там, где домен заканчивается, поэтому отображение нескольких доменов в одно и то же приложение не является проблемой, это будет просто работать.
В терминах IIS вы можете сопоставить столько доменов, сколько хотите (ну, должно быть, ограничение) для одного сайта - я не уверен, можете ли вы использовать подстановочный знак - какую версию IIS вы используете?
Когда приходит запрос, есть события, которые вы можете подключить, чтобы посмотреть на домен и, следовательно, настроить параметры, которые вы хотите (например, пользователь), корневой URL-адрес запроса также доступен из контекста позже в цикле - но вы "Я хочу забрать его раньше".
Если вы можете делать подстановочные знаки, это становится довольно тривиальным - подбирайте запрос, проверяйте субдомен против пользователей в базе данных (если не действительный перенаправление на сайт по умолчанию), задайте пользователя и продолжайте обычную маршрутизацию.
Если вы не можете делать подстановочные знаки, задача заключается в добавлении заголовков хоста к приложению (веб-сайту) IIS "на лету" из вашего приложения, поскольку пользователи добавляются в базу данных.