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