Skip to main content
deleted 306 characters in body
Source Link
    [MustBeListAndContain(Constants.regex_media_id, minimumItems:3, maximumItems: 10, removeDuplicates: true, ErrorMessage = "Ids do not match required format")]
    public List<string> Ids { get; set; }

    [MustBeListAndContain("^[1-3]{1}$", minimumItems: 1, maximumItems: 3, removeDuplicates: true, ErrorMessage = "Types do not match required format")]
    public List<string> Types { get; set; }

The full code

public class MustBeListAndContainAttribute : ValidationAttribute
{
    private Regex regex = null;
    public bool RemoveDuplicates { get; }
    public string Separator { get; }
    public int MinimumItems { get; }
    public int MaximumItems { get; }

    public MustBeListAndContainAttribute(string regexEachItem,
        int minimumItems = 1, 
        int maximumItems = 0,
        string separator = ",",
        bool removeDuplicates = false) : base()
    {
        this.MinimumItems = minimumItems;
        this.MaximumItems = maximumItems;
        this.Separator = separator;
        this.RemoveDuplicates = removeDuplicates;

        if (!string.IsNullOrEmpty(regexEachItem))
            regex = new Regex(regexEachItem, RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.IgnoreCase);            
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        var listOfdValues = (value as List<string>)?[0];

        if (string.IsNullOrWhiteSpace(listOfdValues))
        {
            if (MinimumItems > 0)
                return new ValidationResult(this.ErrorMessage);
            else
                return null;
        };

        var list = new List<string>();

        list.AddRange(listOfdValues.Split(new[] { Separator }, System.StringSplitOptions.RemoveEmptyEntries));

        if (RemoveDuplicates) list = list.Distinct().ToList();

        var prop = validationContext.ObjectType.GetProperty(validationContext.MemberName);
        prop.SetValue(validationContext.ObjectInstance, list);
        value = list;

        if (regex != null)
            if (list.Any(c => string.IsNullOrWhiteSpace(c) || !regex.IsMatch(c)))
                return new ValidationResult(this.ErrorMessage);

        return null;
    }
}
    [MustBeListAndContain(Constants.regex_media_id, minimumItems:3, maximumItems: 10, removeDuplicates: true, ErrorMessage = "Ids do not match required format")]
    public List<string> Ids { get; set; }

    [MustBeListAndContain("^[1-3]{1}$", minimumItems: 1, maximumItems: 3, removeDuplicates: true, ErrorMessage = "Types do not match required format")]
    public List<string> Types { get; set; }

The full code

public class MustBeListAndContainAttribute : ValidationAttribute
{
    private Regex regex = null;
    public bool RemoveDuplicates { get; }
    public string Separator { get; }
    public int MinimumItems { get; }
    public int MaximumItems { get; }

    public MustBeListAndContainAttribute(string regexEachItem,
        int minimumItems = 1, 
        int maximumItems = 0,
        string separator = ",",
        bool removeDuplicates = false) : base()
    {
        this.MinimumItems = minimumItems;
        this.MaximumItems = maximumItems;
        this.Separator = separator;
        this.RemoveDuplicates = removeDuplicates;

        if(!string.IsNullOrEmpty(regexEachItem))
            regex = new Regex(regexEachItem, RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.IgnoreCase);            
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        var listOfdValues = (value as List<string>)?[0];

        if (string.IsNullOrWhiteSpace(listOfdValues)) return new ValidationResult(this.ErrorMessage);

        var list = new List<string>();

        list.AddRange(listOfdValues.Split(new[] { Separator }, System.StringSplitOptions.RemoveEmptyEntries));

        if (RemoveDuplicates) list = list.Distinct().ToList();

        var prop = validationContext.ObjectType.GetProperty(validationContext.MemberName);
        prop.SetValue(validationContext.ObjectInstance, list);
        value = list;

        if (regex != null)
            if (list.Any(c => string.IsNullOrWhiteSpace(c) || !regex.IsMatch(c)))
                return new ValidationResult(this.ErrorMessage);

        return null;
    }
}
public class MustBeListAndContainAttribute : ValidationAttribute
{
    private Regex regex = null;
    public bool RemoveDuplicates { get; }
    public string Separator { get; }
    public int MinimumItems { get; }
    public int MaximumItems { get; }

    public MustBeListAndContainAttribute(string regexEachItem,
        int minimumItems = 1,
        int maximumItems = 0,
        string separator = ",",
        bool removeDuplicates = false) : base()
    {
        this.MinimumItems = minimumItems;
        this.MaximumItems = maximumItems;
        this.Separator = separator;
        this.RemoveDuplicates = removeDuplicates;

        if (!string.IsNullOrEmpty(regexEachItem))
            regex = new Regex(regexEachItem, RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.IgnoreCase);
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        var listOfdValues = (value as List<string>)?[0];

        if (string.IsNullOrWhiteSpace(listOfdValues))
        {
            if (MinimumItems > 0)
                return new ValidationResult(this.ErrorMessage);
            else
                return null;
        };

        var list = new List<string>();

        list.AddRange(listOfdValues.Split(new[] { Separator }, System.StringSplitOptions.RemoveEmptyEntries));

        if (RemoveDuplicates) list = list.Distinct().ToList();

        var prop = validationContext.ObjectType.GetProperty(validationContext.MemberName);
        prop.SetValue(validationContext.ObjectInstance, list);
        value = list;

        if (regex != null)
            if (list.Any(c => string.IsNullOrWhiteSpace(c) || !regex.IsMatch(c)))
                return new ValidationResult(this.ErrorMessage);

        return null;
    }
}
deleted 368 characters in body
Source Link

I createdMy solution was to create an attribute to validate strings, it does a cool (I think) setbunch of validation attributes that does that conversion for you automaticallyextra common features, besides someincluding regex validation that you might need in your casecan use to check for numbers only and then later I convert to integers as wellneeded...

My versionThis is for strings, because attributes don't accept generics yet :(; but it should be easy forhow you to adaptuse:

public class ListMustContainElementsAttribute : ValidationAttribute
{
[MustBeListAndContain(Constants.regex_media_id, minimumItems:3, maximumItems: 10, publicremoveDuplicates: ListMustContainElementsAttribute(inttrue, MinimumItemsErrorMessage = 1, int"Ids MaximumItemsdo =not 0)match :required base(format")]
    public List<string> Ids { get; set; }

    [MustBeListAndContain("^[1-3]{1}$", minimumItems: 1, maximumItems: 3, removeDuplicates: true, this.MinimumItemsErrorMessage = MinimumItems;"Types do not match required format")]
    public List<string> Types { this.MaximumItemsget; =set; MaximumItems;}

The full code

public class MustBeListAndContainAttribute : }ValidationAttribute
{
    private Regex regex = null;
    public intbool MinimumItemsRemoveDuplicates { get; }
    public intstring MaximumItemsSeparator { get; }
 
    public override boolint IsValid(objectMinimumItems value)
{ get; }
  {
  public int MaximumItems { get; }

 var list = valuepublic asMustBeListAndContainAttribute(string IList;regexEachItem,
        if (listint ==minimumItems null)= return1, false;
        if (MinimumItems >int list.Count)maximumItems return= false;0,
        ifstring (MaximumItemsseparator >= 0)",",
        bool removeDuplicates = false) if: base(MaximumItems < list.Count) return false;

     {
   return true;
    }
}

publicthis.MinimumItems class= ListMustContainStringElementsAttributeminimumItems;
 : ListMustContainElementsAttribute
{
    private Regex regexthis.MaximumItems = null;maximumItems;
    private bool removeDuplicates  this.Separator = false;
separator;
    public ListMustContainStringElementsAttribute(string regexEachItem, int MinimumItemsthis.RemoveDuplicates = 1,removeDuplicates;

 int MaximumItems = 0, bool RemoveDuplicates = false) : baseif(MinimumItems, MaximumItems!string.IsNullOrEmpty(regexEachItem))
    {
        regex = new Regex(regexEachItem, RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.IgnoreCase);
         removeDuplicates = RemoveDuplicates;  
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        var commaSeparatedValueslistOfdValues = (value as List<string>)?[0];

        if (string.IsNullOrWhiteSpace(commaSeparatedValueslistOfdValues)) return new ValidationResult(this.ErrorMessage);

        var list = new List<string>();

        list.AddRange(commaSeparatedValueslistOfdValues.Split(new[] { ","Separator }, System.StringSplitOptions.RemoveEmptyEntries));

        if (removeDuplicatesRemoveDuplicates) list = list.Distinct().ToList();

        var prop = validationContext.ObjectType.GetProperty(validationContext.MemberName);
        prop.SetValue(validationContext.ObjectInstance, list);
        value = list;

        if(!base.IsValid(value)) return new ValidationResult(this.ErrorMessage);

        if (regex != null)
            if (list.Any(c => string.IsNullOrWhiteSpace(c) || !regex.IsMatch(c))) return new ValidationResult(this.ErrorMessage);

        return null;
    }
}

then the normal expected usage:

    [Required]
  return new [ListMustContainStringElementsValidationResult(Constantsthis.RegexId, 3, 10, true, ErrorMessage);

 = "Ids do not match required format")]
    public List<string>return Idsnull;
 { get; set; }
}

I created a cool (I think) set of validation attributes that does that conversion for you automatically, besides some validation that you might need in your case as well.

My version is for strings, because attributes don't accept generics yet :(; but it should be easy for you to adapt:

public class ListMustContainElementsAttribute : ValidationAttribute
{
    public ListMustContainElementsAttribute(int MinimumItems = 1, int MaximumItems = 0) : base()
    {
        this.MinimumItems = MinimumItems;
        this.MaximumItems = MaximumItems;
    }

    public int MinimumItems { get; }
    public int MaximumItems { get; }
 
    public override bool IsValid(object value)
    {
        var list = value as IList;
        if (list == null) return false;
        if (MinimumItems > list.Count) return false;
        if (MaximumItems > 0)
            if (MaximumItems < list.Count) return false;

        return true;
    }
}

public class ListMustContainStringElementsAttribute : ListMustContainElementsAttribute
{
    private Regex regex = null;
    private bool removeDuplicates = false;

    public ListMustContainStringElementsAttribute(string regexEachItem, int MinimumItems = 1, int MaximumItems = 0, bool RemoveDuplicates = false) : base(MinimumItems, MaximumItems)
    {
        regex = new Regex(regexEachItem, RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.IgnoreCase);
         removeDuplicates = RemoveDuplicates;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        var commaSeparatedValues = (value as List<string>)?[0];

        if (string.IsNullOrWhiteSpace(commaSeparatedValues)) return new ValidationResult(this.ErrorMessage);

        var list = new List<string>();

        list.AddRange(commaSeparatedValues.Split(new[] { "," }, System.StringSplitOptions.RemoveEmptyEntries));

        if (removeDuplicates) list = list.Distinct().ToList();

        var prop = validationContext.ObjectType.GetProperty(validationContext.MemberName);
        prop.SetValue(validationContext.ObjectInstance, list);
        value = list;

        if(!base.IsValid(value)) return new ValidationResult(this.ErrorMessage);

        if (regex != null)
            if (list.Any(c => string.IsNullOrWhiteSpace(c) || !regex.IsMatch(c))) return new ValidationResult(this.ErrorMessage);

        return null;
    }
}

then the normal expected usage:

    [Required]
    [ListMustContainStringElements(Constants.RegexId, 3, 10, true, ErrorMessage = "Ids do not match required format")]
    public List<string> Ids { get; set; }

My solution was to create an attribute to validate strings, it does a bunch of extra common features, including regex validation that you can use to check for numbers only and then later I convert to integers as needed...

This is how you use:

    [MustBeListAndContain(Constants.regex_media_id, minimumItems:3, maximumItems: 10, removeDuplicates: true, ErrorMessage = "Ids do not match required format")]
    public List<string> Ids { get; set; }

    [MustBeListAndContain("^[1-3]{1}$", minimumItems: 1, maximumItems: 3, removeDuplicates: true, ErrorMessage = "Types do not match required format")]
    public List<string> Types { get; set; }

The full code

public class MustBeListAndContainAttribute : ValidationAttribute
{
    private Regex regex = null;
    public bool RemoveDuplicates { get; }
    public string Separator { get; }
    public int MinimumItems { get; }
    public int MaximumItems { get; }

    public MustBeListAndContainAttribute(string regexEachItem,
        int minimumItems = 1, 
        int maximumItems = 0,
        string separator = ",",
        bool removeDuplicates = false) : base()
    {
        this.MinimumItems = minimumItems;
        this.MaximumItems = maximumItems;
        this.Separator = separator;
        this.RemoveDuplicates = removeDuplicates;

        if(!string.IsNullOrEmpty(regexEachItem))
            regex = new Regex(regexEachItem, RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.IgnoreCase);            
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        var listOfdValues = (value as List<string>)?[0];

        if (string.IsNullOrWhiteSpace(listOfdValues)) return new ValidationResult(this.ErrorMessage);

        var list = new List<string>();

        list.AddRange(listOfdValues.Split(new[] { Separator }, System.StringSplitOptions.RemoveEmptyEntries));

        if (RemoveDuplicates) list = list.Distinct().ToList();

        var prop = validationContext.ObjectType.GetProperty(validationContext.MemberName);
        prop.SetValue(validationContext.ObjectInstance, list);
        value = list;

        if (regex != null)
            if (list.Any(c => string.IsNullOrWhiteSpace(c) || !regex.IsMatch(c)))
                return new ValidationResult(this.ErrorMessage);

        return null;
    }
}
Source Link

I created a cool (I think) set of validation attributes that does that conversion for you automatically, besides some validation that you might need in your case as well.

My version is for strings, because attributes don't accept generics yet :(; but it should be easy for you to adapt:

public class ListMustContainElementsAttribute : ValidationAttribute
{
    public ListMustContainElementsAttribute(int MinimumItems = 1, int MaximumItems = 0) : base()
    {
        this.MinimumItems = MinimumItems;
        this.MaximumItems = MaximumItems;
    }

    public int MinimumItems { get; }
    public int MaximumItems { get; }

    public override bool IsValid(object value)
    {
        var list = value as IList;
        if (list == null) return false;
        if (MinimumItems > list.Count) return false;
        if (MaximumItems > 0)
            if (MaximumItems < list.Count) return false;

        return true;
    }
}

public class ListMustContainStringElementsAttribute : ListMustContainElementsAttribute
{
    private Regex regex = null;
    private bool removeDuplicates = false;

    public ListMustContainStringElementsAttribute(string regexEachItem, int MinimumItems = 1, int MaximumItems = 0, bool RemoveDuplicates = false) : base(MinimumItems, MaximumItems)
    {
        regex = new Regex(regexEachItem, RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.IgnoreCase);
        removeDuplicates = RemoveDuplicates;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        var commaSeparatedValues = (value as List<string>)?[0];

        if (string.IsNullOrWhiteSpace(commaSeparatedValues)) return new ValidationResult(this.ErrorMessage);

        var list = new List<string>();

        list.AddRange(commaSeparatedValues.Split(new[] { "," }, System.StringSplitOptions.RemoveEmptyEntries));

        if (removeDuplicates) list = list.Distinct().ToList();

        var prop = validationContext.ObjectType.GetProperty(validationContext.MemberName);
        prop.SetValue(validationContext.ObjectInstance, list);
        value = list;

        if(!base.IsValid(value)) return new ValidationResult(this.ErrorMessage);

        if (regex != null)
            if (list.Any(c => string.IsNullOrWhiteSpace(c) || !regex.IsMatch(c))) return new ValidationResult(this.ErrorMessage);

        return null;
    }
}

then the normal expected usage:

    [Required]
    [ListMustContainStringElements(Constants.RegexId, 3, 10, true, ErrorMessage = "Ids do not match required format")]
    public List<string> Ids { get; set; }