2012-05-09 4 views
4

私はasp.net mvcの最高のpraticesでDDDの原則を実装するための最良の方法はどのようにいくつかの質問があります。実際、私はあなたがどのように(ビューモデルまたはモデルで)バリデーションを行ってきたのかを知りたいと思いますか?MVCで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"); 
} 

誰かがコードで例を挙げることはできますか?

答えて

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); 
} 

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

ビューモデルの検証に関しては、さまざまな方法があります。 Microsoftの公式の方法を使用することができます。これは、ビューモデルプロパティを検証属性で修飾することです。例:

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

    ... 
} 

個人的に私はこれらの属性を使用しません。私は、あなたが依存プロパティなどを使ってもう少し複雑なバリデーションをしたいときに特に制限があると感じています。この理由から、私はFluentValidation.NETintegrates very nicelyとASP.NET MVCを使用して簡単にunit test私の妥当性検査のルールを許可します。

+0

ありがとうございます。サンプルでは、​​私の製品のCodeプロパティ(例)はユーザー名のように、すべての製品に固有のものです。ビジネスモデルにエラーがある場合は、マップ(VMからDomaniへ)の後に検証し、Viewにエラーを戻すにはどうすればよいですか? –

+0

@felipeoriani、私は私の答えで言ったようにさまざまな方法があります。 1つのアプローチは 'TryXXX'パターンを使うことです。もう1つの方法は、ModelStateディクショナリをビジネス層に渡して、エラーメッセージを直接追加することです。 –

+0

はい、私は後でそれを実装しようとし、私はあなたのaswserを確認するために戻ってきます。ありがとうダーリン...そしてはい、私もFluentValidationを使用することを好む=) –

0

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

関連する問題