468

ASP.NET MVC は初めてです。ViewModel の目的を理解するのに問題があります。

ViewModel とは何ですか? ASP.NET MVC アプリケーションに ViewModel が必要なのはなぜですか?

その動作と説明について良い例があれば、それがより良いでしょう。

4

15 に答える 15

661

Aview modelは、ビュー/ページに表示するデータを表し、静的テキストに使用するか、データベースに追加 (または編集) できる入力値 (テキスト ボックスやドロップダウン リストなど) に使用するかを表します。それはあなたのものとは違うものdomain modelです。ビュー用のモデルです。

従業員ドメイン モデルを表すクラスがありEmployee、次のプロパティ (一意の識別子、名、姓、および作成日) が含まれているとします。

public class Employee : IEntity
{
     public int Id { get; set; }

     public string FirstName { get; set; }

     public string LastName { get; set; }

     public DateTime DateCreated { get; set; }
}

ビュー モデルは、ビューで使用するデータ (プロパティで表される) のみを含むという点で、ドメイン モデルとは異なります。たとえば、新しい従業員レコードを追加したい場合、ビュー モデルは次のようになります。

public class CreateEmployeeViewModel
{
     public string FirstName { get; set; }

     public string LastName { get; set; }
}

ご覧のとおり、2 つのプロパティしか含まれていません。これら 2 つのプロパティは、employee ドメイン モデルにもあります。これはなぜですか? Idビューから設定されない可能性があり、Employee テーブルによって自動生成される可能性があります。またDateCreated、ストアド プロシージャまたはアプリケーションのサービス レイヤーで設定することもできます。そのため、ビュー モデルでは必要ありませんIdDateCreated従業員の詳細 (既にキャプチャされている従業員) を静的テキストとして表示するときに、これら 2 つのプロパティを表示することができます。

ビュー/ページをロードするとき、従業員コントローラーの作成アクション メソッドは、このビュー モデルのインスタンスを作成し、必要に応じてフィールドにデータを入力してから、このビュー モデルをビュー/ページに渡します。

public class EmployeeController : Controller
{
     private readonly IEmployeeService employeeService;

     public EmployeeController(IEmployeeService employeeService)
     {
          this.employeeService = employeeService;
     }

     public ActionResult Create()
     {
          CreateEmployeeViewModel model = new CreateEmployeeViewModel();

          return View(model);
     }

     public ActionResult Create(CreateEmployeeViewModel model)
     {
          // Do what ever needs to be done before adding the employee to the database
     }
}

ビュー/ページは次のようになります (ビュー エンジンを使用していると仮定します) ASP.NET MVC:Razor

@model MyProject.Web.ViewModels.CreateEmployeeViewModel

<table>
     <tr>
          <td><b>First Name:</b></td>
          <td>@Html.TextBoxFor(m => m.FirstName, new { maxlength = "50", size = "50" })
              @Html.ValidationMessageFor(m => m.FirstName)
          </td>
     </tr>
     <tr>
          <td><b>Last Name:</b></td>
          <td>@Html.TextBoxFor(m => m.LastName, new { maxlength = "50", size = "50" })
              @Html.ValidationMessageFor(m => m.LastName)
          </td>
     </tr>
</table>

FirstNameしたがって、検証はとでのみ行われLastNameます。FluentValidationを使用すると、次のような検証が行われる場合があります。

public class CreateEmployeeViewModelValidator : AbstractValidator<CreateEmployeeViewModel>
{
     public CreateEmployeeViewModelValidator()
     {
          RuleFor(m => m.FirstName)
               .NotEmpty()
               .WithMessage("First name required")
               .Length(1, 50)
               .WithMessage("First name must not be greater than 50 characters");

          RuleFor(m => m.LastName)
               .NotEmpty()
               .WithMessage("Last name required")
               .Length(1, 50)
               .WithMessage("Last name must not be greater than 50 characters");
     }
}

データ注釈を使用すると、次のようになります。

public class CreateEmployeeViewModel : ViewModelBase
{
    [Display(Name = "First Name")]
    [Required(ErrorMessage = "First name required")]
    public string FirstName { get; set; }

    [Display(Name = "Last Name")]
    [Required(ErrorMessage = "Last name required")]
    public string LastName { get; set; }
}

覚えておくべき重要なことは、ビュー モデルは使用したいデータのみを表し、それ以外のものは何も表さないということです。30 個のプロパティを持つドメイン モデルがあり、1 つの値のみを更新したい場合、不要なコードと検証がすべて必要になることは想像に難くありません。このシナリオを考えると、ビュー モデルにはこの 1 つの値/プロパティのみがあり、ドメイン オブジェクトにあるすべてのプロパティはありません。

ビュー モデルは、1 つのデータベース テーブルからのデータだけではありません。別のテーブルのデータを組み合わせることができます。新しい従業員レコードの追加に関する上記の例を見てください。姓名だけでなく、従業員の部署も追加したい場合があります。この部門のリストは、Departmentsテーブルから取得されます。これで、EmployeesDepartmentsテーブルのデータが 1 つのビュー モデルに含まれるようになりました。次に、次の 2 つのプロパティをビュー モデルに追加し、データを入力する必要があります。

public int DepartmentId { get; set; }

public IEnumerable<Department> Departments { get; set; }

従業員データ (データベースに既に追加されている従業員) を編集する場合、上記の例と大差ありません。ビュー モデルを作成し、たとえば と呼びますEditEmployeeViewModel。姓名など、このビュー モデルで編集するデータのみを保持します。データを編集し、送信ボタンをクリックします。値はおそらく URL に含まれているIdため、フィールドについてはあまり心配しません。次に例を示します。Id

http://www.yourwebsite.com/Employee/Edit/3

これIdを受け取り、名前と姓の値とともに、リポジトリ レイヤーに渡します。

レコードを削除するときは、通常、編集ビュー モデルと同じパスに従います。たとえば、次のような URL もあります。

http://www.yourwebsite.com/Employee/Delete/3

ビューが初めてロードされると、Idof 3 を使用してデータベースから従業員のデータを取得します。次に、ビュー/ページに静的テキストを表示して、どの従業員が削除されているかをユーザーが確認できるようにします。ユーザーが [削除] ボタンをクリックすると、Id値 3 を使用してリポジトリ レイヤーに渡します。Idテーブルからレコードを削除するだけです。

もう 1 つのポイントとして、すべてのアクションにビュー モデルは必要ありません。単純なデータであれば、 のみを使用しても問題ありませんEmployeeViewModel。複雑なビュー/ページであり、それらが互いに異なる場合は、それぞれに別のビュー モデルを使用することをお勧めします。

これで、ビュー モデルとドメイン モデルに関する混乱が解消されることを願っています。

于 2012-06-17T20:21:52.190 に答える
140

ビュー モデルは、特定のビューで使用されるデータ モデルを表すクラスです。このクラスをログイン ページのモデルとして使用できます。

public class LoginPageVM
{
    [Required(ErrorMessage = "Are you really trying to login without entering username?")]
    [DisplayName("Username/e-mail")]
    public string UserName { get; set; }
    [Required(ErrorMessage = "Please enter password:)")]
    [DisplayName("Password")]
    public string Password { get; set; }
    [DisplayName("Stay logged in when browser is closed")]
    public bool RememberMe { get; set; }
}

このビュー モデルを使用して、ビュー (Razor ビュー エンジン) を定義できます。

@model CamelTrap.Models.ViewModels.LoginPageVM

@using (Html.BeginForm()) {
    @Html.EditorFor(m => m);
    <input type="submit" value="Save" class="submit" />
}

そしてアクション:

[HttpGet]
public ActionResult LoginPage()
{
    return View();
}

[HttpPost]
public ActionResult LoginPage(LoginPageVM model)
{
    ...code to login user to application...
    return View(model);
}

この結果が生成されます(フォームを送信した後に画面が取得され、検証メッセージが表示されます):

ご覧のとおり、ビュー モデルには多くの役割があります。

  • ビューモデルは、ビューで表されるフィールドのみで構成されるビューを文書化します。
  • ビュー モデルには、データ注釈または IDataErrorInfo を使用した特定の検証規則が含まれる場合があります。
  • ビュー モデルは、ビューがどのように見えるかを定義します ( LabelForEditorForDisplayForヘルパーの場合)。
  • ビュー モデルは、異なるデータベース エンティティの値を組み合わせることができます。
  • ビュー モデルの表示テンプレートを簡単に指定し、DisplayFor または EditorFor ヘルパーを使用して多くの場所で再利用できます。

ビュー モデルとその取得の別の例: 基本的なユーザー データ、権限、およびユーザー名を表示します。必須フィールドのみを含む特別なビュー モデルを作成します。データベースからさまざまなエンティティからデータを取得しますが、ビューはビュー モデル クラスのみを認識します。

public class UserVM {
    public int ID { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public bool IsAdministrator { get; set; }
    public string MothersName { get; set; }
}

検索:

var user = db.userRepository.GetUser(id);

var model = new UserVM() {
   ID = user.ID,
   FirstName = user.FirstName,
   LastName = user.LastName,
   IsAdministrator = user.Proviledges.IsAdministrator,
   MothersName = user.Mother.FirstName + " " + user.Mother.LastName
} 
于 2012-06-16T14:41:50.793 に答える
92
于 2015-03-19T01:30:59.010 に答える
22

ビューに固有のプロパティがあり、DB/サービス/データ ストアに関連していない場合は、ViewModel を使用することをお勧めします。たとえば、DB フィールド (または 2 つ) に基づいてチェックボックスを選択したままにしておく必要がありますが、DB フィールド自体はブール値ではありません。モデル自体でこれらのプロパティを作成し、データへのバインディングから隠しておくことは可能ですが、そのようなフィールドやトランザクションの量によっては、モデルを乱雑にしたくない場合があります。

ビュー固有のデータや変換が少なすぎる場合は、モデル自体を使用できます

于 2012-06-16T14:44:39.910 に答える
20

すべての投稿を読んだわけではありませんが、すべての回答には、「理解する」のに本当に役立つ概念が1つ欠けているようです...

Model がデータベースのTableに似ている場合、ViewModel はデータベースのViewに似ています。ビューは通常、1 つのテーブルから少量のデータを返すか、複数のテーブル (結合) から複雑なデータ セットを返します。

ViewModels を使用して情報をビュー/フォームに渡し、フォームがコントローラーにポストバックするときにそのデータを有効なモデルに転送していることに気付きました。Lists(IEnumerable) の保存にも非常に便利です。

于 2016-09-09T20:53:25.650 に答える
11

多くの大きな例を、明確かつサクサクした方法で説明させてください。

ViewModel = ビューを提供するために作成されたモデル。

ASP.NET MVC ビューは複数のモデルを持つことができないため、複数のモデルのプロパティをビューに表示する必要がある場合、それは不可能です。ViewModel はこの目的を果たします。

ビュー モデルは、ビューに必要なプロパティのみを保持できるモデル クラスです。また、データベースの複数のエンティティ (テーブル) からのプロパティを含めることもできます。名前が示すように、このモデルはビューの要件に合わせて作成されます。

ビューモデルのいくつかの例を以下に示します

  • ビュー ページに複数のエンティティからのデータを一覧表示するには、ビュー モデルを作成し、データを一覧表示するすべてのエンティティのプロパティを設定します。これらのデータベース エンティティを結合し、ビュー モデル プロパティを設定してビューに戻り、さまざまなエンティティのデータを 1 つの表形式で表示します
  • ビュー モデルは、ビューに必要な単一エンティティの特定のフィールドのみを定義できます。

ViewModel は、レコードを複数のエンティティに挿入、更新するためにも使用できますが、ViewModel の主な用途は、複数のエンティティ (モデル) の列を単一のビューに表示することです。

ViewModel の作成方法は Model の作成と同じで、Viewmodel のビューの作成方法は Model のビューの作成と同じです。

ViewModel を使用した List データの小さな例を次に示します。

これが役立つことを願っています。

于 2016-01-29T07:46:26.617 に答える
11

MVC にはビューモデルがありません。モデル、ビュー、およびコントローラーがあります。ビューモデルは MVVM (Model-View-Viewmodel) の一部です。MVVM はプレゼンテーション モデルから派生したもので、WPF で普及しています。MVVM にもモデルがあるはずですが、ほとんどの人はそのパターンのポイントを完全に見逃しており、ビューとビューモデルしかありません。MVC のモデルは、MVVM のモデルに似ています。

MVC では、プロセスは 3 つの異なる責任に分割されます。

  • ビューは、ユーザーにデータを提示する責任があります
  • コントローラーはページ フローを担当します。
  • モデルはビジネス ロジックを担当します。

MVC は Web アプリケーションにはあまり適していません。これは、デスクトップ アプリケーションを作成するために Smalltalk によって導入されたパターンです。Web 環境の動作はまったく異なります。デスクトップ開発から 40 年前の概念をコピーして、それを Web 環境に貼り付けるのはあまり意味がありません。ただし、多くの人は、アプリケーションがコンパイルされて正しい値が返されるため、これで問題ないと考えています。それは、私の意見では、特定のデザインの選択をOKと宣言するのに十分ではありません.

Web アプリケーションのモデルの例は次のとおりです。

public class LoginModel
{
    private readonly AuthenticationService authentication;

    public LoginModel(AuthenticationService authentication)
    {
        this.authentication = authentication;
    }

    public bool Login()
    {
        return authentication.Login(Username, Password);
    }

    public string Username { get; set; }
    public string Password { get; set; }
}

コントローラーは次のように使用できます。

public class LoginController
{
    [HttpPost]
    public ActionResult Login(LoginModel model)
    {
        bool success = model.Login();

        if (success)
        {
            return new RedirectResult("/dashboard");
        }
        else
        {
            TempData["message"] = "Invalid username and/or password";
            return new RedirectResult("/login");
        }
    }
}

コントローラーのメソッドとモデルは小さく、簡単にテストでき、的を射ています。

于 2015-12-03T16:04:21.153 に答える
7

ViewModel は、MVC フレームワークの概念的な不器用さにパッチを当てる回避策です。これは、3 層のモデル - ビュー - コントローラー アーキテクチャの 4 番目の層を表します。モデル (ドメイン モデル) が適切でなく、ビューに対して大きすぎる (2 ~ 3 フィールドよりも大きい) 場合は、より小さな ViewModel を作成してビューに渡します。

于 2017-10-03T09:03:51.657 に答える
1

ビュー モデルは、データの概念モデルです。たとえば、サブセットを取得したり、異なるテーブルからデータを結合したりするために使用されます。

特定のプロパティのみが必要な場合があるため、これにより、それらのプロパティのみをロードし、追加の不要なプロパティをロードすることはできません

于 2018-09-21T09:16:41.793 に答える
1

ViewModel は、mvc ビューで使用するフィールドを含むモデルです。ビューに ViewModel を使用すると、次の利点があります。

  • データベースモデル(Entityクラス)には単一のテーブルのデータが含まれているため。複数のテーブルからのデータが必要な場合、1 つの Viewmodel に複数のテーブルのフィールドを含めることができます。
  • ユーザーはデータベース モデルを直接操作できないため、データベース レイヤーまたはモデルは保護されます。
  • リポジトリを介してデータベースモデルからデータを取得し、ビューに渡すために使用されます。同様に、データベースモデルにデータを投稿してデータベースレコードを更新するために利用します。
于 2020-07-19T19:45:36.123 に答える