マスターページ”ロジックはMVCに行きますか?
-
05-07-2019 - |
質問
MVCを試していますが、私の質問は次のとおりです。
- 異なるホストヘッダーにより、サイトの(1つの)マスターページ、つまりすべてのページに異なるページタイトルが表示されます。たとえば、ホストヘッダーがhello.mydomain.comの場合、ページタイトルは" Hello World"でなければなりません。 goodbye.mydomain.comは「Goodbye World」である必要があります。すべてのページ/ビュー。
- ホストヘッダーがリストにあるものと異なる場合は、アプリケーションのどこにいても、/ Error / NoHostHeaderにリダイレクトする必要があります。
以前は、これをMasterPage Load()イベントに入れていましたが、MVCのように見えますが、これはすべてのコントローラーで行うことができます(すべてのコントローラーでこの機能を呼び出す必要はありません)。またはGlobal.asaxのどこかにあります(グローバルすぎるようです)。
編集:これは、実際にデータを処理するためのControllerと組み合わせたGlobal.asaxメソッドを使用して正常に機能するようになりました。この時点で唯一の問題は、すべてのホストヘッダー情報がデータベースにあることです。通常、「テナント」を保存します。 Session変数を使用し、DB変数が存在しない場合にのみDB呼び出しを行う場合の情報。これを行うためのより良い方法はありますか?
解決
MVCには1つの理由で1対1の同等物はありません。MVCの方法で考える方法を繰り返しましょう。
モデル:"このサイトのページは常に特定のコンテキストでリクエストされます。それをテナント(またはユーザー、トピック、またはサブドメインが表すもの)と呼びましょう。ドメインモデルには、現在のリクエストのテナントを表すプロパティがあります。"
表示:"モデルに設定されているテナントに応じてページタイトルをレンダリングします。
コントローラー:"ホストヘッダーに応じてモデルにテナントを設定します"。
避けたいのは、コントローラー、ビュー、ビジネスロジックを混合することです。 「コントローラー」と呼ばれない1つまたは複数の場所にコントローラーロジックがある分離されている限り問題ありません。
そして今、良いこと:この「MVCスタイル」を行うことができます。 Webフォームを使用した場合でも、ASP.NET MVCでもソリューションは機能します!
リクエストのライフサイクル(ページのライフサイクルではない)が残っているため、すべてのリクエストのコントローラーロジックのこの部分を含むカスタムHttpModuleを実装できます。 BeginRequestイベントを処理し、ホストヘッダーを確認し、テナントをHttpContext.Current.Items [" tenant"]のようなものに保存します。 (もちろん、このディクショナリエントリの静的な型付きラッパーを使用できます。)
その後、すべてのモデルオブジェクト(またはモデルの基本クラス、またはソリューションに適したもの)がHttpContextにアクセスして、次のようにこの情報へのアクセスを提供できます。
public string Tenant
{
get { return HttpContext.Current.Items["tenant"]; }
}
利点:
- 原因(ホストヘッダー)と結果(ページタイトルのレンダリング)を分離し、保守性とテスト容易性を改善しました
- したがって、現在のテナントに応じてデータベースからコンテンツをロードするなど、この状態に基づいてドメインモデルに簡単に追加の動作を追加できます。
- CSSファイルやロゴ画像など、テナントに依存するビューのより多くの部分を簡単に作成できます
- コントローラのロジックを後で変更して、サブドメインだけでなく、Cookie、リファラー、検索語、ユーザーエージェントの言語など、考えられるものに基づいてモデルにテナントを設定することもできます。モデルに応じてコードを変更します。
更新して編集:セッション内の状態を保持することは、特にセッションCookieが各サブドメインだけでなくすべてのドメインに適用される可能性がある場合、私は好きではありません。この場合、ユーザーが以前に別のサブドメインを訪問した場合、一貫性のないコンテンツを提供する可能性があります。おそらく、ホストヘッダーをテナントにマッピングしているデータベース内の情報はあまり頻繁に変更されないため、キャッシュすることができ、リクエストごとにデータベースを検索する必要はありません。
他のヒント
MVCマスターページビューに正しいViewDataを提供するベースコントローラーを作成し、そのコントローラーから実際の各コントローラーを派生させることができます。ロジックをActionExecutingメソッドに入れると、必要に応じて例外を生成したり、エラーページにリダイレクトしたりできるはずです。
あなたも考えています" WebForms" MVCが十分ではありません。マスターページはビューの単なるラッパーであり、レイアウトhtmlのみを含める必要があります。マスターに物を送ることはできますが、それは一方通行の道であり、不可知論的な見解に努力する必要があります。要するに、ここでは使用されないため、WebFormsにあったイベントは忘れてください。
Hostヘッダーを扱っているので、それをGlobal.asaxに入れることができると思います...今、私は混乱しています:P
http://forums.asp.net/t/1226272.aspx <から盗まれたコード/ a>
protected void Application_BeginRequest(object sender, EventArgs e)
{
string host = string.Empty;
if (this.Request.ServerVariables["HTTP_HOST"] == this.Request.Url.DnsSafeHost)
{
host = this.Request.Url.DnsSafeHost;
}
else
{
Regex regex = new Regex("http://[^/]*.host/([^/]*)(/.*)");
Match match = regex.Match(this.Request.Url.AbsoluteUri);
if (match.Success)
{
host = match.Groups[1].Value;
Context.RewritePath(match.Groups[2].Value);
}
}
// Match the host with the portal in the database
...
}