Нужна помощь с MVC 3 для создания пользовательских валидаторов в лучшем виде на свойствах коллекции - PullRequest
0 голосов
/ 28 июля 2011

Я застрял с созданием пользовательских валидаторов для удовлетворения бизнес-правил нашего проекта.

Теперь ниже приведена модель:

открытый класс CreateTestModel { public CreateTestModel () {

    [Required]
    public string Name { get; set; }

    public string Description { get; set; }

    public string BucketValidator { get; set; }

    public RadioButtonListViewModel<GoalTypes> Goals { get; set; }

    [EntityValidator(Property1:"IncludedEntities",Property2:"ExcludedEntities",MandatoryCount:1,isBucket=false, ErrorMessage = "One Entity is Compulsory")]
    public IEnumerable<TestEntityModel> IncludedEntities { get; set; }

    public IEnumerable<TestEntityModel> ExcludedEntities { get; set; }


    public int MandatoryEntityCount { get; set; }

    public IEnumerable<TestFilterModel> IncludedFilters { get; set; }

    public IEnumerable<TestFilterModel> ExcludedFilters { get; set; }
  [EntityValidator(Property1:"Buckets",Property2:"",MandatoryCount:2,isBucket=true,ErrorMessage = "Bucket is compulsory")]

    [DisplayName("BucketErrors")]

    public IEnumerable<BucketModel> Buckets { get; set; }

    public bool AutoDecision { get; set; }

    public DateTime StartDate { get; set; }

    public DateTime EndDate { get; set; }

    public int AdminId { get; set; }

    [DefaultValue(true)]
    public bool IsEnabled { get; set; }
}

по приведенной выше модели я создал валидатор Entity, который используется для удовлетворения моих бизнес-правил. Но так как проверка должна проводиться в свойствах коллекции, Validator не может выдать ошибку, когда существует более одного значения в коллекции, иначе он проверяет сгенерированные ошибки.

Класс EntityValidator указан ниже:

[AttributeUsage (AttributeTargets.Property, AllowMultiple = false, Inherited = true)]

public class EntityValidator : ValidationAttribute,IClientValidatable
{
    public int numberOfMandatoryEntities{get; private set;}
    public int totalCountofIncludeEntities { get; private set; }
    public bool isBucket { get; set; }
    public string Property1{get; private set;}
    public string Property2{ get; private set; }
    private const string DefaultErrorMessageFormatString = "Atleast one entity is required";

    public EntityValidator(string Property1, string Property2, int MandatoryCount)
    {
        this.Property1 = Property1;
        if (!String.IsNullOrEmpty(Property2))
            this.Property2 = Property2;
        numberOfMandatoryEntities = MandatoryCount;
    }

    public EntityValidator(string Property1,string Property2,int MandatoryCount,bool isBucket)
    {
        this.Property1 = Property1;
        if(!String.IsNullOrEmpty(Property2))
        this.Property2 = Property2;
        this.isBucket = isBucket;
        numberOfMandatoryEntities = MandatoryCount;
    }

    public override string FormatErrorMessage(string name)
    {
        return string.Format(ErrorMessageString, name);
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        object property2Value = null;
        object property1Value = null;
        int property1Count=0;
        int trafficCount = 0;
        if(!String.IsNullOrEmpty(Property2))
        property2Value = validationContext.ObjectInstance.GetType().GetProperty(Property2).GetValue(validationContext.ObjectInstance, null);
        property1Value = validationContext.ObjectInstance.GetType().GetProperty(Property1).GetValue(validationContext.ObjectInstance, null);
        if (property1Value != null)
        {
        property1Count = ((IEnumerable<Object>)property1Value).Count();
            if (isBucket)
            {

                IEnumerable<BucketModel> bucket = ((IEnumerable<BucketModel>)property1Value);

                var result = bucket.Select(x => x.TrafficPercentage);
                foreach (var i in result)
                {
                    trafficCount = trafficCount + i;
                }
            }

        }
        if(isBucket)
        {
            if(trafficCount<100)
            {
                var x = new ValidationResult(string.Format("Percentage total cannot be less than 100 %", validationContext.DisplayName));
                return x;
            }
        }
        if (property2Value != null)
        {
            property1Count = property1Count +((IEnumerable<Object>)property2Value).Count();
        }
        if (property1Count < numberOfMandatoryEntities)
        {
            return new ValidationResult(ErrorMessage);
        }

        return ValidationResult.Success;
    }
    #region IClientValidatable Members

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        var x = new ModelClientValidationRule();
        x.ValidationType = "entityvalidator";
        x.ErrorMessage = string.Format(ErrorMessageString, metadata.GetDisplayName());
        x.ValidationParameters.Add("mandatoryentity", numberOfMandatoryEntities);
        x.ValidationParameters.Add("checkforbucket", isBucket);

        return new[] 
        {  
            x
        };
    }

Теперь проблемы:

1) Когда в коллекции более одного значения, IsValid возвращает ошибку, но не обнаруживается привязкой к какому-либо свойству в ModelState! Добавление псевдо-свойства является вариантом, но что может быть лучше?

2) Легко использовать эту клиентскую сторону валидатора, добавив псевдо-свойства для каждого правила, указав функцию в правилах проверки клиента и добавив адаптер в валидированный. Но этот подход не кажется очень уместным и просто кажется обходным путем, есть ли лучший способ сделать это ??

Пожалуйста, помогите ...! Заранее спасибо ....

1 Ответ

0 голосов
/ 28 июля 2011

Когда правила проверки усложняются, как в вашем случае, я бы порекомендовал вам оставить аннотации данных и перейти к FluentValidation.NET , который имеет отличную интеграцию с ASP.NET MVC (I используйте его постоянно, а не только тогда, когда правила проверки усложняются). Что касается правил проверки клиента, то он поддерживает большинство общих правил, но когда он становится сложным, вам лучше писать собственные адаптеры.

...