2010-02-23 50 views
4

我正在创建一个更好理解的示例。一个类mvc上的多个自定义验证属性

[CustomValidator("Property1","Property2", ErrorMessage= "Error1")] 
[CustomValidator("Property3","Property4", ErrorMessage= "Error1")] 
public class MyViewModel 
{ 
    public string Property1 {get; set;} 
    public string Property2 {get; set;} 
    public string Property3 {get; set;} 
    public string Property4 {get; set;} 
} 

[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false)] 
public class CustomValidator : ValidationAttribute 
{ 
    All the required stuff is written. 
} 

只有第二个验证器(或列表中的最后一个)被触发并忽略第一个验证器。 我不确定这是否适合这种情况。 有什么建议吗?

+0

您是否找到了解决方案?我有同样的问题。我不想实现IValidatableObject,因为我需要在多个类上使用MetadataType。 – jrummell 2011-06-17 17:17:35

+0

找到解决办法,看我的答案。 – jrummell 2011-06-17 17:31:34

回答

1

如果你正在使用LINQ to SQL的,为什么不尝试这样的事情

添加违规类来处理违规

public class RuleViolation 
{ 
    public string ErrorMessage { get; private set; } 
    public string PropertyName { get; private set; } 
    public RuleViolation(string errorMessage) 
    { 
     ErrorMessage = errorMessage; 
    } 
    public RuleViolation(string errorMessage, string propertyName) 
    { 
     ErrorMessage = errorMessage; 
     PropertyName = propertyName; 
    } 
} 
现在

你的数据类

[Bind(Exclude="ID")] 
public partial class Something 
{ 
    public bool IsValid 
    { 
     get { return (GetRuleViolations().Count() == 0); } 
    } 

    public IEnumerable<RuleViolation> GetRuleViolations() 
    { 
     if (String.IsNullOrEmpty(Name.Trim())) 
      yield return new RuleViolation("Name Required", "Name"); 
     if (String.IsNullOrEmpty(LocationID.ToString().Trim())) 
      yield return new RuleViolation("Location Required", "LocationID"); 
     yield break; 
    } 

    partial void OnValidate(ChangeAction action) 
    { 
     if (!IsValid) 
      throw new ApplicationException("Rule violations prevent saving"); 
    } 

} 

和在您的控制器的更新方法中,使用updatemodel方法更改属性

Something something = somethingRepo.GetSomething(id); 
try 
{ 
    //update something 
    UpdateModel(something); 
    somethingRepo.Save(); 
    return RedirectToAction("Index"); 
} 
catch 
{ 
    ModelState.AddRuleViolations(something.GetRuleViolations()); 
    return View(something); 
} 

这样你可以将规则添加到您的数据类,因为它的变化,它会在你的更新中反映出来,等

+0

感谢您的建议。 我使用实体框架,并且我有一个备份来验证它(类似于您的建议)。 但我想在视图模型中捕获这些错误。 更确切地说,Property1和Property2是十进制类型,并希望确保一个比另一个大。 我只是不能让所有的验证器触发,如果在一个类上定义了多个,只有最后一个工作。 – Kesh 2010-02-24 14:01:31

0

你不真的为你的模型创建元数据类需要所有的代码使用的数据注解link text

应该设置你在正确的道路上还宣读了对HTML助手和好友类(这就是他们所说的EM)

+0

那么,我正在做什么是simialr你说什么,但在班级而不是属性。 我必须比较2个属性,所以我不得不创建一个自定义类来比较。 – Kesh 2010-02-24 14:03:24

0

我有同样的问题。

我想出了以下解决方案。

您的POCO类可能会实现接口IValidatableObject。

这需要您从以下方法实施。

public virtual IEnumerable<ValidationResult> Validate(ValidationContext validationContext) 
    { 
     // return list of appropriate ValidationResult object    
     var customResult = new List<ValidationResult>(); 
     customResult.Add(new ValidationResult("message", new List<string>(){"Property1"}); 
    } 

您可以在其中放置任何验证逻辑。这也比类级属性更有优势。类级属性只能在ValidationSummary中显示(它们与任何属性无关)。与此相反,您可以在返回ValidationResult时设置特定的成员。这允许显示消息所涉及的特定控件旁边的验证信息。

相关问题