私はレイアウトページを持つウェブサイトを持っています。ただし、このレイアウト ページには、すべてのページ モデルが、ページ タイトル、ページ名、アクションを実行する HTML ヘルパーの実際の場所などを提供する必要があるデータがあります。また、各ページには独自のビュー モデル プロパティがあります。
これどうやってするの?レイアウトを入力するのは悪い考えのようですが、これらの情報を渡すにはどうすればよいですか?
私はレイアウトページを持つウェブサイトを持っています。ただし、このレイアウト ページには、すべてのページ モデルが、ページ タイトル、ページ名、アクションを実行する HTML ヘルパーの実際の場所などを提供する必要があるデータがあります。また、各ページには独自のビュー モデル プロパティがあります。
これどうやってするの?レイアウトを入力するのは悪い考えのようですが、これらの情報を渡すにはどうすればよいですか?
各ページに同じプロパティを渡す必要がある場合は、すべてのビュー モデルで使用される基本ビューモデルを作成するのが賢明です。レイアウト ページは、この基本モデルを取ることができます。
このデータの背後に必要なロジックがある場合は、すべてのコントローラーで使用されるベース コントローラーに配置する必要があります。
できることはたくさんありますが、重要なアプローチは、同じコードを複数の場所で繰り返さないことです。
編集:以下のコメントから更新
概念を説明する簡単な例を次に示します。
すべてのビュー モデルが継承するベース ビュー モデルを作成します。
public abstract class ViewModelBase
{
public string Name { get; set; }
}
public class HomeViewModel : ViewModelBase
{
}
レイアウト ページは、これをモデルとして使用できます。
@model ViewModelBase
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Test</title>
</head>
<body>
<header>
Hello @Model.Name
</header>
<div>
@this.RenderBody()
</div>
</body>
</html>
最後にアクションメソッドにデータを設定します。
public class HomeController
{
public ActionResult Index()
{
return this.View(new HomeViewModel { Name = "Bacon" });
}
}
レイアウトのカミソリに RenderAction html ヘルパーを使用しました。
@{
Html.RenderAction("Action", "Controller");
}
単純な文字列に必要でした。したがって、私のアクションは文字列を返し、それを簡単に書き留めます。ただし、複雑なデータが必要な場合は、PartialViewResult とモデルを返すことができます。
public PartialViewResult Action()
{
var model = someList;
return PartialView("~/Views/Shared/_maPartialView.cshtml", model);
}
作成した部分ビュー '_maPartialView.cshtml' の先頭にモデルを配置するだけです。
@model List<WhatEverYourObjeIs>
次に、html を使用してその部分ビューでモデルのデータを使用できます。
もう 1 つのオプションは、レイアウトに必要なすべてのプロパティを含む別の LayoutModel クラスを作成し、このクラスのインスタンスを ViewBag に詰め込むことです。Controller.OnActionExecuting メソッドを使用して設定します。次に、レイアウトの開始時に、このオブジェクトを ViewBag から引き戻し、この厳密に型指定されたオブジェクトにアクセスし続けることができます。
これを処理する別の方法があります。アーキテクチャの観点からは最もクリーンな方法ではないかもしれませんが、他の回答に伴う多くの苦痛を回避できます。Razor レイアウトにサービスを挿入し、必要なデータを取得するメソッドを呼び出すだけです。
@inject IService myService
その後、レイアウト ビューで次の操作を行います。
@if (await myService.GetBoolValue()) {
// Good to go...
}
繰り返しますが、アーキテクチャに関してはきれいではありません (明らかに、サービスをビューに直接挿入するべきではありません) が、仕事は完了します。
私がしたことは非常に簡単で、うまくいきます
任意のコントローラーで Static プロパティを宣言するか、次のようにしたい場合は、静的な値を持つデータクラスを作成できます。
public static username = "Admin";
public static UserType = "Administrator";
これらの値は、操作に基づいてコントローラによって更新できます。後で_Layoutで使用できます
_layout.cshtml 内
@project_name.Controllers.HomeController.username
@project_name.Controllers.HomeController.UserType
これを行う代わりに、いつでも高速な別のアプローチを使用できます
共有ディレクトリに新しい部分ビューを作成し、レイアウトで部分ビューを次のように呼び出します。
@Html.Partial("MyPartialView")
部分ビューでは、データベースを呼び出して、やりたいことを実行できます
@{
IEnumerable<HOXAT.Models.CourseCategory> categories = new HOXAT.Models.HOXATEntities().CourseCategories;
}
<div>
//do what ever here
</div>
Entity Framework データベースを追加したと仮定して
ここで誰もこれを言わなかったのは信じられないことです。ベースコントローラーを介してビューモデルを渡すのは面倒です。ユーザー クレームを使用してレイアウト ページに情報を渡します (たとえば、ナビゲーション バーにユーザー データを表示するため)。もう1つ利点があります。データは Cookie を介して保存されるため、各リクエストでパーシャルを介してデータを取得する必要はありません。グーグルで「asp net identity claim」を実行するだけです。
次のように使用できます。
@{
ApplicationDbContext db = new ApplicationDbContext();
IEnumerable<YourModel> bd_recent = db.YourModel.Where(m => m.Pin == true).OrderByDescending(m=>m.ID).Select(m => m);
}
<div class="col-md-12">
<div class="panel panel-default">
<div class="panel-body">
<div class="baner1">
<h3 class="bb-hred">Recent Posts</h3>
@foreach(var item in bd_recent)
{
<a href="/BaiDangs/BaiDangChiTiet/@item.ID">@item.Name</a>
}
</div>
</div>
</div>
</div>