2009-10-19 53 views
5

針對不同動作驗證模型的最佳做法是什麼,例如,用於創建和刪除的不同驗證規則?asp.net mvc針對不同動作的不同驗證規則

謝謝!

澄清:我認爲這需要一些澄清,因爲答案似乎不能解決問題。

例如,

創建人 驗證了有姓名,年齡和電子郵件沒有被使用 刪除個人 驗證該人是不是家長。業務邏輯規定父母不能被消除

我如何有這兩種不同的驗證方案?

回答

2

據我所知,你想要更多的控制你的驗證規則。您可以手動添加驗證規則,如下所述:MVC 2.0 Client validation exposed這使您可以完全控制如何組織驗證,哪些規則添加在哪個操作上等。

1

使用像FluentValidation或NHibernate Validators這樣的驗證庫來進行驗證。將此代碼移動到模型綁定器中,以便每當模型通過時,它都會自動進行驗證。你可以看一下如果你使用ASP.NET MVC 1,您將檢查DataAnnotationsModelBinder擴展與FluentValidation

public class FluentValidationModelBinder : DefaultModelBinder { 
     private readonly IValidatorFactory _validatorFactory; 

     public FluentValidationModelBinder(IValidatorFactory validatorFactory) { 
      _validatorFactory = validatorFactory; 
     } 

     protected override void OnModelUpdated(ControllerContext controllerContext, ModelBindingContext bindingContext) { 
      var model = bindingContext.Model; 
      base.OnModelUpdated(controllerContext, bindingContext); 
      IValidator validator = _validatorFactory.GetValidator(bindingContext.ModelType); 
      if (validator != null) { 
       var result = validator.Validate(model); 
       if (!result.IsValid) { 
        result.AddToModelState(bindingContext.ModelState, ""); 
       } 
      } 
     } 
    } 
0

如果你想使用ASP.NET MVC(XVAL,數據註釋屬性等)的一些驗證框架的唯一驗證模型的字段的子集爲特定的動作,最簡單的解決方案是使用[Bind]屬性。

雖然我當然可以想到一種情況,您可能只想驗證模型字段的子集(即在Create操作中),但我無法想到您希望驗證特定字段的情況在兩種不同的行爲之間完全不同。

下面是一個簡單的例子,將Person模型對象與Data Annotations驗證器屬性結合使用。 CreateUpdate動作將針對模型的不同字段進行驗證。


型號

public class Person 
{ 
    [Required] 
    Int32 Id { get; set; } 

    [Required] 
    String FirstName {get; set;} 

    [Required] 
    String LastName {get; set;} 
} 


控制器操作

[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult Create([Bind(Exclude = "Id")] Person person) 
{ 
    // this action will not perform any validation checks against the Id property of the model 
} 

[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult Update(Person person) 
{ 
    // this action will perform validation checks against all model properties, including Id 
} 

在上面的例子中,Create動作將會完全忽略該Id模型對象的Person屬性。它不會試圖綁定這個屬性,也不會嘗試對它進行任何驗證。由於一個人在創作時沒有身份證,這正是你想要的。另一方面,Update動作將綁定並驗證模型的所有屬性。

在方法參數上指定Bind屬性可以使代碼在醜陋的一面有點。但是,如果列表變長,您總是可以添加一些額外的換行符和空白來幫助減少醜陋。

1

澄清:我認爲這需要一些澄清,因爲答案似乎沒有解決問題。

例如,

創建人驗證了有姓名,年齡和電子郵件沒有被使用刪除個人驗證該人是不是家長。業務邏輯規定父母不能被消除

我如何有這兩種不同的驗證方案?

「封裝什麼變化」。

完成此操作的一種方法是使用命令模式,並將驗證應用於命令而不是實體。這裏有一個簡單的例子,沒有使用任何驗證框架,但想法是一樣的。

public class Blub 
{ 
    public int BlubId { get; set; } 
    public string Name { get; set; } 
    public bool SomeBlockingCondition { get; set; } 
} 

public class BlubEditController : Controller 
{ 
    [AcceptVerbs(HttpVerbs.Get)] 
    public ActionResult Rename(int blubId) 
    { 
     var ctx = new DataContext(); 
     var blub = ctx.Blubs.Single(o => o.BlubId==blubId); 
     return ShowRenameForm(blub); 
    } 

    [AcceptVerbs(HttpVerbs.Post)] 
    public ActionResult Rename(int blubId, RenameCommand cmd) 
    { 
     var ctx = new DataContext(); 
     var blub = ctx.Blubs.Single(o => o.BlubId==blubId); 

     cmd.Subject = blub; 

     if (cmd.Validate(ModelState, "cmd.")) 
     { 
      cmd.Execute(); 
      ctx.SubmitChanges(); 
      return RedirectToAction("Show", new { blubId = blubId }); 
     } 
     else 
     { 
      return ShowRenameForm(blub); 
     } 
    } 
} 

public class RenameCommand 
{ 
    public Blub Subject { get; set; } 

    public string Name { get; set; } 

    public bool Validate(ModelStateDictionary modelState, string prefix) 
    { 
     if (Subject.SomeBlockingCondition) 
     { 
      modelState.AddModelError(prefix + "SomeBlockingCondition", "No!"); 
      return false; // Optional shortcut return to prevent further validation. 
     } 

     if (String.IsNullOrEmpty(this.Name)) 
     { 
      modelState.AddModelError(prefix + "Name", "Seriously, no."); 
     } 

     return modelState.IsValid; 
    } 

    public void Execute() 
    { 
     Subject.Name = this.Name; 
    } 
} 
+0

很好的答案。謝謝 – user10479 2009-11-04 13:53:43

0

我認爲,對於這種情況,只需在域中編寫一些代碼DELETE的模型(BLL)來判斷是否可以刪除某個Person,或者在sql或sp中編寫一些代碼,並返回一個值,以便在刪除完成時專用。