4

asp.net mvc のベスト プラクティスを使用して DDD の原則を実装する最善の方法について、いくつか質問があります。実際、(ビューモデルまたはモデルで) 検証をどのように行っていますか?

私はこの DomainModel と ViewModel を持っています:

public class Product {
   public int Id { get; protected set; }
   public string Name { get; set; }
   public decimal Price { get; set; }
   public int Stock { get; set; }
   public Category Category { get; set; }
   public Supplier Supplier { get; set; }
   public string Code { get; set; } // it has to be unique
}

public class ProductViewModel {
   public int Id { get; set; }
   /* other simple properties */
   public int IdCategory { get; set; }
   public int IdSupplier { get; set; }
   public string Code { get; set; } 
}

Ok。モデルは NHibernate でマッピングされ、正常に動作します。ViewModel または DomainModel の検証を作成する方がよいかどうかを知りたいですか? つまり、asp.net mvc のアクションで ViewModel を受け取ったら検証しますが、ViewModel にビジネス ルールを追加すると、間違っていないでしょうか。これらのビジネス検証を自分のドメインに追加した方がよいとわかっているので、これを尋ねますが、永続化する前に投稿で 2 つの検証を行う必要がありますか? asp.net mvc で私のアクションを見てください:

[Post]
public ActionResult Update(ProductViewModel viewModel) {

  // what kind of validations should I do here? 
  if (invalid) {
    return View(viewModel);
  } 

  // how can I return the errors to my View?

  // Is here any best pratice to transform from ViewModel to Domain instance?
  Product product = ???

  _repository.Save(product);

  return RedirectToAction("Index");
}

誰かがコードで例を示すことができますか?

4

2 に答える 2

9

2 つのレベルで検証を実行する必要があります。ビューモデルでは、たとえば、このフィールドは必須であり、このフィールドは次の形式でなければならないなどの表面検証を行いますが、ビジネスレイヤーでは、ユーザー名が既に存在するなどのビジネスルールを検証する必要があります...

それでは、典型的な POST アクションがどのように見えるかの例を見てみましょう:

[HttpPost]
public ActionResult Update(ProductViewModel viewModel) 
{
    if (!ModelState.IsValid) 
    {
        // The view model is invalid => redisplay the view in order
        // to show the error messages
        return View(viewModel);
    }    

    // at this stage we know that the view model is valid =>
    // now we can map it to a domain model that we want to update:

    Product product = Repository.GetModel(viewModel.Id);

    // I use AutoMapper (http://automapper.org/) to map between 
    // my domain models and my view models. In this example
    // we are updating only the properties of the domain model
    // that were part of the view model and that the user is allowed
    // to modify in this view => we are merging
    Mapper.Map<ProductViewModel, Product>(viewModel, product);

    // now we can process the domain model
    Repository.Update(product);

    return RedirectToAction("Index");
}

また、ドメイン モデルのエラーを処理したい場合は、さまざまな可能性があります。TryXXX個人的には次のパターンが好きです。

string errorMessage;
if (!Repository.TryUpdate(product, out errorMessage))
{
    // the business validation failed => add the error message to the modelstate
    // and redisplay the view
    ModelState.AddModelError("", errorMessage);
    return View(viewModel);
}

もう 1 つの可能性は、ModelState辞書をビジネス層に渡して、モデル状態エラーを直接追加させることです。このようにして、ビジネス レイヤーで問題が発生したかどうかを確認するためにビューでもう一度簡単にテストif (!ModelState.IsValid)し、同じビューを再表示してエラー メッセージを表示することができます。

ビュー モデルでの検証に関する限り、さまざまな方法があります。ビューモデルのプロパティを検証属性で装飾するというMicrosoftの公式の方法を使用できます。例えば:

public class ProductViewModel 
{
    [Required]
    public string Foo { get; set; }

    ...
}

個人的には、これらの属性は使用しません。特に、依存プロパティなどでもう少し複雑な検証を行いたい場合は、それらが非常に制限的であることがわかります。このため、私はFluentValidation.NETを使用しています。FluentValidation.NET は ASP.NET MVC と非常にうまく統合されており、検証ルールの単体テストを簡単に行うことができます。

于 2012-05-09T14:02:34.417 に答える
0

ビュー モデルに適用される検証規則は、ドメイン モデルのものと必ずしも同じではありません。通常、ビュー モデルの入力エラーをチェックし、ドメイン モデルのビジネス ルール違反をチェックします。一部の検証ルールは両方のモデルで同じになりますが、ドメイン モデルはビュー モデルから独立しているため、これは問題ありません。

于 2012-05-11T09:19:44.697 に答える