2010-02-23 1 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

+0

Нашли решение, см. Мой ответ. – jrummell

ответ

1

, если вы используете Linq для 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 и Property 2 имеют тип decimal и хотели бы удостовериться, что один из них больше другого. Я просто не могу заставить все валидаторы стрелять, если несколько классов определены в классе, работает только последний. – Kesh

0

вы действительно не нужны все, что аннотации использования кода данных путем создания класса МЕТАДАННЫХ для вашей модели link text

, которые должны установить вас на правильном пути также прочитать на HTML хелперов и классов напарников (это то, что они называют их)

+0

Ну, что я делаю, это похоже на то, что вы говорите, но на уровне класса вместо свойств. Мне нужно сравнить 2 свойства, поэтому мне пришлось создать собственный класс для сравнения. – Kesh

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. Это позволяет показать информацию проверки, относящуюся к определенному элементу управления, к которому относится сообщение.

Смежные вопросы