web-dev-qa-db-ja.com

ASP.NET MVC Razorはモデルをレイアウトに渡します

表示されるのは、文字列のLayoutプロパティです。しかし、モデルを明示的にレイアウトに渡すにはどうすればよいですか?

87
SiberianGuy

この問題がある場合、ビューモデルを少し間違ってモデル化しているようです。

個人的には、レイアウトページを入力することはありません。ただし、それを行うには、他のビューモデルが継承するベースビューモデルを用意し、ベースビューモデルにレイアウトを入力し、特定の1回ページングする必要があります。

64

これはかなり基本的なものです。必要なのは、ベースビューモデルを作成し、すべてを確認することだけです!そして、私はすべてを意味します!そのレイアウトを使用するビューのうち、そのベースモデルを使用するビューを受け取ります!

public class SomeViewModel : ViewModelBase
{
    public bool ImNotEmpty = true;
}

public class EmptyViewModel : ViewModelBase
{
}

public abstract class ViewModelBase
{
}

_Layout.cshtml内:

@model Models.ViewModelBase
<!DOCTYPE html>
  <html>
  and so on...

ホームコントローラーの(たとえば)Indexメソッドで:

    public ActionResult Index()
    {
        var model = new SomeViewModel()
        {
        };
        return View(model);
    }

index.cshtml:

@model Models.SomeViewModel

@{
  ViewBag.Title = "Title";
  Layout = "~/Views/Shared/_Layout.cshtml";
}

<div class="row">

モデルを_layoutに渡すことはエラーであり、一部のユーザー情報を渡すことができ、コントローラーの継承チェーンにデータを取り込むことができるため、1つの実装のみが必要であることに同意しません。

明らかに、より高度な目的のためには、インジェクションを使用してカスタムの静的コンタクを作成することを検討し、_Layout.cshtmlにそのモデルの名前空間を含める必要があります。

しかし、基本的なユーザーのために、これはトリックを行います

26
Yakir Manor

一般的な解決策は、レイアウトファイルで使用されるプロパティを含むベースビューモデルを作成し、ベースモデルから各ページで使用されるモデルに継承することです。

このアプローチの問題は、他の1つのクラスからしか継承できないモデルの問題に自分自身を固定していることであり、解決策として、とにかく意図したモデルで継承を使用できない場合があります。

私のソリューションは、ベースビューモデルからも始まります。

public class LayoutModel
{
    public LayoutModel(string title)
    {
        Title = title;
    }

    public string Title { get;}
}

次に使用するのは、次のように、LayoutModelを継承するLayoutModelの汎用バージョンです。

public class LayoutModel<T> : LayoutModel
{
    public LayoutModel(T pageModel, string title) : base(title)
    {
        PageModel = pageModel;
    }

    public T PageModel { get; }
}

このソリューションで、レイアウトモデルとモデルの間で継承を行う必要性を切り離しました。

そこで、次のようにLayout.cshtmlのLayoutModelを使用できます。

@model LayoutModel
<!doctype html>
<html>
<head>
<title>@Model.Title</title>
</head>
<body>
@RenderBody()
</body>
</html>

また、ページ上では、次のような一般的なLayoutModelを使用できます。

@model LayoutModel<Customer>
@{
    var customer = Model.PageModel;
}

<p>Customer name: @customer.Name</p>

コントローラーから、LayoutModel型のモデルを返すだけです:

public ActionResult Page()
{
    return View(new LayoutModel<Customer>(new Customer() { Name = "Test" }, "Title");
}
14
Oskar Sjöberg

必要なモデルを部分ビューに渡し、最後にRenderPartialまたはRenderActionを使用してLayout.cshtmlで上記の部分ビューをレンダリングするi固有のコントローラーを持つ新しい部分ビューを追加しないのはなぜですか?

このメソッドを使用して、名前、プロフィール写真などのログインしているユーザーの情報を表示します。

11
Arya Sh

古い質問ですが、MVC5開発者向けのソリューションに言及するために、ビューと同じModelプロパティを使用できます。

ビューとレイアウトの両方のModelプロパティは同じViewDataDictionaryオブジェクトに関連付けられているため、レイアウトページにモデルを渡すために特別な作業を行う必要はありません。レイアウトで@model MyModelNameを宣言します。

ただし、レイアウトで@Model.XXXを使用すると、ModelViewBagと同様の動的オブジェクトであるため、intelliSenseコンテキストメニューが表示されないことに注意してください。

2
Laz Ziya

技術的にそれを処理する適切な方法ではないかもしれませんが、私にとって最も簡単で合理的な解決策は、クラスを作成してレイアウトでインスタンス化することです。それは、そうでなければ正しい方法の1回限りの例外です。これがレイアウトよりも多く行われている場合、プロジェクトをさらに進める前に、自分のやっていることを真剣に考え直し、さらにいくつかのチュートリアルを読む必要があります。

public class MyLayoutModel {
    public User CurrentUser {
        get {
            .. get the current user ..
        }
    }
}

その後、ビューで

@{
    // Or get if from your DI container
    var myLayoutModel = new MyLayoutModel();
}

.netコアでは、それをスキップして依存性注入を使用することもできます。

@inject My.Namespace.IMyLayoutModel myLayoutModel

これらの分野の1つは日陰です。しかし、私がここで見ている非常に複雑な代替案を考えると、実用性の名の下に作ることは大した例外ではないと思います。特に、シンプルに保ち、重いロジック(実際には存在するべきではないが、要件は異なると主張する)が、それが属する別のクラス/レイヤーにあることを確認する場合。基本的に1つだけのビューのために、すべてのコントローラーまたはモデルを汚染するよりも確かに優れています。

1
computrius

モデルがオブジェクトのコレクション(または単一のオブジェクト)であると仮定しましょう。モデル内の各オブジェクトに対して、次を実行します。

1)表示するオブジェクトをViewBagに配置します。例えば:

  ViewBag.YourObject = yourObject;

2)_Layout.cshtmlの上部に、オブジェクトのクラス定義を含むusingステートメントを追加します。例えば:

@using YourApplication.YourClasses;

3)_LayoutでyourObjectを参照すると、キャストされます。 (2)で行ったことにより、キャストを適用できます。

0
HappyPawn8