7

ViewModelsの使用を始めたばかりです。このコードをチェックして、私がベストプラクティスに従っているかどうかを確認できますか?何か変わったことはありますか?検証を別の方法で行いますか?

コードが長い場合は申し訳ありません(コードには非常に多くの部分があります)。できるだけわかりやすくするように心がけました。

ありがとう!

モデル

  public class CustomerModel
  {
    [Required(ErrorMessage="Primer nombre!")]
    public string FirstName { get; set; }

    [Required(ErrorMessage="Segundo nombre!")]
    public string LastName { get; set; }

    [Required(ErrorMessage="Edad")]
    public int? Age { get; set; }

    public string State { get; set; }
    public string CountryID { get; set; }

    [Required(ErrorMessage="Phone Number")]
    public string PhoneNumber { get; set; }
  }

ViewModel

  public class CustomerViewModel
  {
    public CustomerModel Customer { get; set; }

    public string Phone1a { get; set; }
    public string Phone1b { get; set; }
    public string Phone1c { get; set; }
  }

コントローラ

    public ActionResult Index()
    {
      CustomerViewModel Customer = new CustomerViewModel()
      {
        Customer = new CustomerModel(),
      };


      return View(Customer);
    }


    [HttpPost]
    public ActionResult Index(CustomerViewModel c)
    {

      //ModelState.Add("Customer.PhoneNumber", ModelState["Phone1a"]);

      // Let's manually bind the phone number fields to the PhoneNumber properties in
      // Customer object. 
      c.Customer.PhoneNumber = c.Phone1a + c.Phone1b + c.Phone1c;

      // Let's check that it's not empty and that it's a valid phone number (logic not listed here)
      if (!String.IsNullOrEmpty(c.Customer.PhoneNumber))
      {
        // Let's remove the fact that there was an error! 
        ModelState["Customer.PhoneNumber"].Errors.Clear();
      } // Else keep the error there. 

      if (ModelState.IsValid)
      {
        Response.Write("<H1 style'background-color:white;color:black'>VALIDATED</H1>");
      }
      return View("Index", c);
    }

  }

意見

@model MVVM1.Models.CustomerViewModel

@using (Html.BeginForm("Index", "Detail"))
{  
  <table border="1" cellpadding="1" cellspacing="1">
    <tr>
      <td>@Html.LabelFor(m => m.Customer.FirstName)</td>
      <td>
        @Html.TextBoxFor(m => m.Customer.FirstName)
        @Html.ValidationMessageFor(m => m.Customer.FirstName)
      </td>
    </tr>
    <tr>
      <td>@Html.LabelFor(m => m.Customer.LastName)</td>
      <td>
        @Html.TextBoxFor(m => m.Customer.LastName)
        @Html.ValidationMessageFor(m => m.Customer.LastName)
      </td>
    </tr>
    <tr>
      <td>@Html.LabelFor(m => m.Customer.Age)</td>
      <td>
        @Html.TextBoxFor(m => m.Customer.Age)
        @Html.ValidationMessageFor(m => m.Customer.Age)
      </td>
    </tr>

    <tr>
      <td>@Html.LabelFor(m => m.Customer.PhoneNumber)</td>
      <td width="350">
        @Html.TextBoxFor(m => m.Phone1a, new { size="4", maxlength="3" })
        @Html.TextBoxFor(m => m.Phone1b)
        @Html.TextBoxFor(m => m.Phone1c)
        <div>
        @Html.ValidationMessageFor(m => m.Customer.PhoneNumber)
        </div>
      </td>
    </tr>
    <tr>
      <td></td>
      <td>
        <input type="submit" value="Submit" /></td>
    </tr>
  </table>
}
4

3 に答える 3

2

私に飛び出すことの1つはこれです:

  if (ModelState.IsValid) 
  { 
    Response.Write("<H1 style'background-color:white;color:black'>VALIDATED</H1>"); 
  } 
  return View("Index", c); 

ビューモデルは、データをコントローラーに渡したり、モデルに戻したりするのに適していることに注意してください。Response.Write を呼び出す代わりに、IsValid プロパティをビュー モデルに追加し、それを true に設定することをお勧めします。次に、これを部分ビューの上部に追加するだけです:

@if (Model.IsValid)
{
    <H1 style'background-color:white;color:black'>VALIDATED</H1>
}

ビューで ModelState にアクセスすることもできますが、それはベスト プラクティスではないと主張する人もいます。ただし、ビューに表示されるだけのプロパティをモデルに追加したくない場合は、次のようにします。

@if (ViewData.ModelState.IsValid)

もう 1 つの気の利いた点は、MVC 検証属性は通常、UI での検証に使用されることです。この検証は他の領域で再利用できますが、場合によっては最適ではありません。また、ドメイン モデルを常に変更できるとは限りません。したがって、すべての UI 検証を 1 か所に保持するために、通常はドメイン モデルをビュー モデルにラップして、次のようにします。

public class CustomerViewModel                      
{                      
    public CustomerModel Customer { get; set; }

    [Required(ErrorMessage="Primer nombre!")]                        
    public string FirstName
    {
        get { return Customer.FirstName; } 
        set { Customer.FirstName = value; }
    }
...

これは冗長に思えるかもしれませんし、常に努力する価値があるとは限りませんが、変更が困難または不可能な Entity Framework ドメイン モデルやその他のクラスを使用する場合は、検討することをお勧めします。

于 2012-02-18T03:47:30.327 に答える
2

私は MVC のコツをつかんだところですが、昨日同じトピックを調査したところ、ViewModel にモデル オブジェクトを直接含めるべきではないという結論に達しました。したがって、CustomerViewModel に直接 CustomerModel を含めるのは悪い習慣だと私は理解しています。

代わりに、ViewModel に含めたい CustomerModel の各プロパティを一覧表示する必要があります。次に、データを CustomerModel から CustomerViewModel に手動でマップするか、AutoMapper などのツールを使用して、アクション メソッド内の次のようなコード行で自動的にマップします。

public ViewResult Example()
{
    // Populate/retrieve yourCustomer here
    Customer yourCustomer = new CustomerModel();

    var model = Mapper.Map<CustomerModel, CustomerViewModel>(yourCustomer);

    return View(model);
}

この場合、Mapper.Map はビューに渡すことができる CustomerViewModel を返します。

また、Application_Start メソッドに以下を含める必要があります。

Mapper.CreateMap<CustomerModel, CustomerViewModel>();

一般に、AutoMapper は非常に簡単に作業できることがわかりました。フィールド名が一致する場合は自動的に行われます。一致しない場合、またはネストされたオブジェクトがある場合は、CreateMap 行でこれらのマッピングを指定できます。したがって、CustomerModel が個々のプロパティではなく Address オブジェクトを使用する場合は、次のようにします。

Mapper.CreateMap<CustomerModel, CustomerViewModel>()
    .ForMember(dest => dest.StreetAddress, opt => opt.MapFrom(src => src.Address.Street));

MVCについても頭を悩ませているだけなので、間違っている場合は誰かに訂正してください。

于 2012-02-23T15:06:06.750 に答える
1

ViewModelの実装はかなり標準的だと思います。ViewModelを使用して、ビューとドメインモデルの間の中間オブジェクトとして機能します。これは良い習慣です。

私がうんざりするのは、モデルエラーの処理方法だけです。また、ViewModelにはいくつかの属性が必要です。たとえば、次のRegularExpressionAttributeクラスを使用できます。

  public class CustomerViewModel
  {
    public CustomerModel Customer { get; set; }

    [RegularExpression(@"^\d{3}$")]
    public string Phone1a { get; set; }
    [RegularExpression(@"^\d{3}$")]
    public string Phone1b { get; set; }
    [RegularExpression(@"^\d{4}$")]
    public string Phone1c { get; set; }
  }
于 2012-02-18T02:48:47.710 に答える