asp.net mvcの動的サブドメイン
-
10-07-2019 - |
質問
私はasp.netを初めて使用しますが、iisの経験はほとんどありません。アプリケーションの各ユーザーに独自のサブドメインを取得させたいのですが、全員が同じコントローラーを使用しています。サブドメインは、表示されるコンテンツを制御します。
例:
user1subdomain.mydomain.com/Whatever
user2subdomain.mydomain.com/Whatever
両方が同じコントローラーを使用します。理想的には、パラメーターがユーザー名をコントローラーに提供し、コントローラーが適切なコンテンツを表示できることが理想的です。新しいサブドメインが追加されるたびにルーティングルールを書き換えることなく、新しいサブドメインをデータベースに追加できるように十分な柔軟性を持たせたい。
解決
MVCはドメインにバインドされず、パスにのみバインドされます(例: http:// domain / path )。
これを適切に行うには、次のものが必要です...
- のワイルドカードDNS設定 * .yourdomain.comはサーバーを指します。
- IISセットアップのサイト ホストヘッダーなし。その他のサイト IISのそのインスタンスでホストされています 同じIPにはHostヘッダーが必要です 指定されています。
- アプリケーションは、 ページの読み込み時にホストヘッダーをリクエストする、 セッション開始またはその他のイベント。
他のヒント
この人のブログで簡単な答えを見つけました。これがうまく機能し、このソリューションが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アプリケーション(Webサイト)にホストヘッダーを追加することが課題になります。