アプリケーションの説明によると、それはかなり標準的なもののようであり、意図した方法で DataAnnotations を使用しても問題はありません。ここでは、アプリケーションがどのように構造化されているか (不足している詳細を埋めるため) についていくつかの仮定を立て、ビジネスの検証に DataAnnotations をどのように使用できるかを説明します。
ビジネス層は、アプリケーション ドメインを反映するオブジェクト モデルで構成されていると想定しています。ドメイン モデル内の各オブジェクトは、ビジネス ルールを実装する属性と潜在的なメソッドを公開します。これは、検証をコーディングするアプリケーション層であり、実際、ドメイン検証ルールに適した場所です。
データ アクセス レイヤーに Entity Framework または同様の ORM を使用していると仮定しています。
MVC コントローラーは、ドメイン モデルに直接アクセスしません。代わりに、ViewModel (データ転送オブジェクトと呼びます) を使用して、個々のビューのデータを適切に構造化します。したがって、ViewModel には、ドメイン検証規則が適用されるドメイン モデルから抽象化されたデータが含まれます。
さて、これはすべて問題なく、意図したとおりです。特定のビューのドメイン検証規則をオーバーライドする場合は、ViewModel のプロパティに他の DataAnnotations を追加できますが、必須ではありません。ただし、クライアント側の検証はビュー モデル プロパティに対して MVC によって実行されますが、基になるドメイン オブジェクトに対しては実行されません。
したがって、ModelState.IsValid
この場合、メソッドを使用しても機能しません。ドメイン モデルで検証を実行するにはDbEntityValidationException
、オブジェクトを保存しようとした後にトラップできます。
[HttpPost]
public ActionResult Edit(int id, BlogView view)
{
try
{
Blog blog = Mapper.Map(view); //map view model to domain object using eg. Automapper
db.Entry(blog).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
catch(DbEntityValidationException ex)
{
var error = ex.EntityValidationErrors.First().ValidationErrors.First();
this.ModelState.AddModelError(error.PropertyName, error.ErrorMessage);
return View();
}
}
EntityFramework によってスローされた例外に依存したくない場合は、DbContext.GetValidationErrors()
メソッドを使用して明示的に検証をトリガーできます。
foreach (var validationResults in db.GetValidationErrors())
{
foreach (var error in validationResults.ValidationErrors)
{
Debug.WriteLine("Entity Property: {0}, Error {1}",
error.PropertyName,error.ErrorMessage);
}
}
または、ドメイン オブジェクトでIValidatableObject
インターフェースを実装し、その Validate() メソッドを使用することもできます。
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (Title == BloggerName)
{
yield return new ValidationResult
("Blog Title cannot match Blogger Name", new[] { "Title", “BloggerName” });
}
}
詳細については、 http://msdn.microsoft.com/en-gb/data/gg193959.aspxを参照してください。