ASP MVC 3の1つのビューに2つのモデル


91

私には2つのモデルがあります。

public class Person
{
    public int PersonID { get; set; }
    public string PersonName { get; set; }
}
public class Order
{
    public int OrderID { get; set; }
    public int TotalSum { get; set; }
}

SINGLEビューで両方のクラスのオブジェクトを編集したいので、次のようなものが必要です。

@model _try2models.Models.Person
@model _try2models.Models.Order

@using(Html.BeginForm())
{
    @Html.EditorFor(x => x.PersonID)
    @Html.EditorFor(x => x.PersonName)
    @Html.EditorFor(x=>x.OrderID)
    @Html.EditorFor(x => x.TotalSum)
}

もちろん、これは機能しません。.cshtmlファイルでは、1つの「モデル」ステートメントしか使用できません。いくつかの回避策がありますか?


1
私の答えはあなたを助けますか?
Andrew

ViewBagはfor each in viewを使用して動作しました。これをチェックして複数のオプションを確認し、ビューモデルまたは部分ビューを作成する代わりに時間を少し節約しました
shaijut

回答:


118

両方のモデルを含む親ビューモデルを作成します。

public class MainPageModel{
    public Model1 Model1{get; set;}
    public Model2 Model2{get; set;}
}

このようにして、最小限の労力で後日追加のモデルを追加できます。


2
このソリューションを使用する場合は、Model1またはModel2を変更すると、MainPageModelに影響が及ぶ可能性があることに注意してください。また、ビューには実際に必要なデータよりも多くのデータが含まれています。MainPageが既に他のコントローラーにあるものの組み合わせである場合、RenderPartialからRenderActionに切り替えると、適切に分離された状態を維持できます。デメテルの法則を読むことを検討してください:en.wikipedia.org/wiki/Law_of_Demeter
Fenton

1
@Andi-上記で提案したようにモデルを作成しました。しかし、コントローラーを右クリックしてCrudコントローラーを作成しようとすると、機能しませんか?助言がありますか?上記のモデルの自動ビューでクラッドコントローラを作成するにはどうすればよいですか?
NoviceMe 2012

2
この問題を解決するために私が見たすべてのアプローチの中で、これは私にとって最もうまくいった方法です。これは、最も簡単に機能するソリューションです。
Ciaran Gallagher 2013

4
「なんで前にそんなこと考えなかったの?」と思った瞬間 優れたソリューション
Rafael AMS 2014

1
@Andiコントローラでそれぞれのモデルのメソッドをどのように公開しますか?
Volatil3 2014年

53

タプルを使用するには、次のことを行う必要があります。ビューでモデルを次のように変更します。

@model Tuple<Person,Order>

@htmlメソッドを使用するには、次の操作を行う必要があります。

@Html.DisplayNameFor(tuple => tuple.Item1.PersonId)

または

@Html.ActionLink("Edit", "Edit", new { id=Model.Item1.Id }) |

Item1はTupleメソッドに渡される最初のパラメーターを示し、Item2を使用して2番目のモデルにアクセスできます。

コントローラーでタプル型の変数を作成し、ビューに渡す必要があります。

    public ActionResult Details(int id = 0)
    {
        Person person = db.Persons.Find(id);
        if (person == null)
        {
            return HttpNotFound();
        }
        var tuple = new Tuple<Person, Order>(person,new Order());

        return View(tuple);
    }

別の例:ビュー内の複数のモデル


1
Tupleこの場合は絶対に a を使用し ないでください -OPはデータを編集する必要があり、aにTupleはデフォルトのコンストラクターがないため、フォームの送信時にモデルをバインドできません

絶対とは絶対言うな。ここは少し強いです。
ジョニー

47

カスタムモデルを作成する必要がないもう1つのオプションは、Tuple <>を使用することです。

@model Tuple<Person,Order>

Andiの回答のように、両方を含む新しいクラスを作成するほどきれいではありませんが、実行可能です。


mvc 3ではエラーが発生する1つのファイルで許可される「モデル」ステートメントは1つだけです。それを解決する方法はありますか?
GibboK、2012年

1
@GibboK-私はMVC3で問題なく使用しています。2つの別々の@model行がないことを確認しますか?
ボブソン2012年

3
各モデルのプロパティは、次を使用して取得できます:@Model.Item1.Propertyおよび@Model.Item2.Propertyfor PersonおよびOrder
user2019515

1
ビューでタプルを使用しました。しかし、コントローラーでモデル値を取得できません。しかし、@ Andiが推奨するように親ビューモデルを使用している間、コントローラーでモデル値を取得しました。
Naren 14年

1
@StephenMuecke-うーん。私はそれを考えたことはありませんが、あなたは正しいです。Andrewの回答のも​​う1つの理由は、より優れた汎用的な回答です。あなたは(このような)軽量の代替に行くとき、あなたはない機能をあきらめます。
ボブソン2016年

10

非常にフラットなモデルが好きで、ビューをサポートするだけの場合は、この特定のビューに固有のモデルを作成する必要があります...

public class EditViewModel
    public int PersonID { get; set; }
    public string PersonName { get; set; }
    public int OrderID { get; set; }
    public int TotalSum { get; set; }
}

多くの人々はAutoMapperを使用して、ドメインオブジェクトからフラットビューにマップします。

ビューモデルの考え方は、ビューをサポートするだけで、それ以外はサポートしないというものです。そのビューに必要なものだけが含まれ、他のビューに必要なプロパティのロードが含まれていないことを確認するために、ビューごとに1つあります。


5

わかりました、誰もが理にかなっているので、私はすべての部分を取り、ここに配置して、説明を終わらせる必要がある私のような初心者を支援します。

@Andrewの回答に従って、2つのクラスを保持する大きなクラスを作成します。

public class teamBoards{
    public Boards Boards{get; set;}
    public Team Team{get; set;}
}

次に、コントローラーで2つのモデルを入力します。場合によっては、1つだけ入力する必要があります。次に、戻りで大きなモデルを参照すると、2つの内部がビューに表示されます。

            TeamBoards teamBoards = new TeamBoards();


        teamBoards.Boards = (from b in db.Boards
                               where b.TeamId == id
                               select b).ToList();
        teamBoards.Team = (from t in db.Teams
                              where t.TeamId == id
                          select t).FirstOrDefault();

 return View(teamBoards);

ビューの上部

@model yourNamespace.Models.teamBoards

次に、大きなモデルのコンテンツを参照する入力または表示をロードします。

 @Html.EditorFor(m => Model.Board.yourField)
 @Html.ValidationMessageFor(m => Model.Board.yourField, "", new { @class = "text-danger-yellow" })

 @Html.EditorFor(m => Model.Team.yourField)
 @Html.ValidationMessageFor(m => Model.Team.yourField, "", new { @class = "text-danger-yellow" })

そして。。。牧場で.back、投稿が来たらビッグクラスを参照:

 public ActionResult ContactNewspaper(teamBoards teamboards)

そして、モデルが返したものを利用します:

string yourVariable = teamboards.Team.yourField;

おそらくクラスにいくつかのDataAnnotation Validation要素があり、おそらく保存/編集ブロックの上部にif(ModelState.IsValid)を置きます。。。


4

実際、両方を含むクラスにラップせずに、1つのビューで2つ以上のモデルを使用する方法があります。

サンプルモデルとしてのEmployeeの使用:

@model Employee

実際に扱われます。

@{ var Model = ViewBag.model as Employee; }

したがって、View(employee)メソッドはモデルをViewBagに設定し、ViewEngineがそれをキャストしています。

この意味は、

ViewBag.departments = GetListOfDepartments();
    return View(employee);

のように使用できます

            @model  Employee
        @{
                var DepartmentModel = ViewBag.departments as List<Department>;
        }

基本的に、ViewBagにあるものは何でも「モデル」として使用できます。それが、とにかくそれが機能する方法だからです。これがアーキテクチャ上理想的だと言っているわけではありませんが、それは可能です。


3

必要なすべての情報を含む単一のビューモデルを作成するだけで、通常はすべてのビューのモデルを作成するので、すべてのビューに固有にすることも、親モデルを作成して継承することもできます。または、両方のビューを含むモデルを作成します。

個人的には、それらを1つのモデルに追加するだけですが、それは私が行う方法です。

public class xViewModel
{
    public int PersonID { get; set; }
    public string PersonName { get; set; }
    public int OrderID { get; set; }
    public int TotalSum { get; set; }
}

@model project.Models.Home.xViewModel

@using(Html.BeginForm())
{
    @Html.EditorFor(x => x.PersonID)
    @Html.EditorFor(x => x.PersonName)
    @Html.EditorFor(x => x.OrderID)
    @Html.EditorFor(x => x.TotalSum)
}

1

プレゼンテーションパターンを使用できますhttp://martinfowler.com/eaaDev/PresentationModel.html

このプレゼンテーションの「ビュー」モデルには、PersonとOrderの両方を含めることができます。この新しい
クラスは、ビューが参照するモデルにすることができます。


1
プレゼンテーションモデルには、実際には必要なデータが含まれている必要があります。PersonまたはOrderドメインオブジェクトを実際に含むべきではありません。ビューは、基になるドメインから表示を切り離します。
フェントン

0

話されていないもう1つの方法は、表示するすべてのデータを使用してMSSQLでビューを作成することです。次に、LINQ to SQLなどを使用してマッピングします。コントローラでそれをビューに戻します。できました。


0

1つのビューで2つのモデルを宣言することはできません。Html.Action("Person", "[YourController]")&を使用してみてくださいHtml.Action("Order", "[YourController]")

幸運を。


これは何をしますか?
ジョニー

0

asp.netの1つのビューモデルのほかに、複数の部分ビューを作成して、すべてのビューに異なるモデルビューを割り当てることもできます。次に例を示します。

   @{
        Layout = null;
    }

    @model Person;

    <input type="text" asp-for="PersonID" />
    <input type="text" asp-for="PersonName" />

次に、注文モデルの別の部分ビューモデル

    @{
        Layout = null;
     }

    @model Order;

    <input type="text" asp-for="OrderID" />
    <input type="text" asp-for="TotalSum" />

次に、メインビューで両方の部分ビューをロードします

<partial name="PersonPartialView" />
<partial name="OrderPartialView" />

-1

お役に立てば幸いです。

プロジェクトにはViewBagを使用し、タスクにはModelを使用するため、このようにして、単一のビューとコントローラーで2つのモデルを使用しています。viewbagの値またはデータを定義しました。

List<tblproject> Plist = new List<tblproject>();
            Plist = ps.getmanagerproject(c, id);

            ViewBag.projectList = Plist.Select(x => new SelectListItem
            {
                Value = x.ProjectId.ToString(),
                Text = x.Title
            });

ビューでtbltaskとprojectlistは私の2つのdiffモデルです

@ {

IEnumerable<SelectListItem> plist = ViewBag.projectList;

@モデルリスト

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.