[ACCEPTED]-Required Attribute on Generic List Property-generic-list
Adding the Required
attribute to a list-style property 18 doesn't really do what you want. The will 17 complain if the list isn't created, but 16 won't complain if the list exists with 0 15 item in it.
However, it should be easy enough 14 to derive your own data annotations attribute 13 and make it check the list for Count
> 0. Something 12 like this (not tested yet):
[AttributeUsage(AttributeTargets.Property)]
public sealed class CannotBeEmptyAttribute : ValidationAttribute
{
private const string defaultError = "'{0}' must have at least one element.";
public CannotBeEmptyAttribute ( ) : base(defaultError) //
{
}
public override bool IsValid ( object value )
{
IList list = value as IList;
return ( list != null && list.Count > 0 );
}
public override string FormatErrorMessage ( string name )
{
return String.Format(this.ErrorMessageString, name);
}
}
EDIT:
You'll also 11 have to be careful how you bind your list 10 in your view. For example, if you bind a 9 List<String>
to a view like this:
<input name="ListName[0]" type="text" />
<input name="ListName[1]" type="text" />
<input name="ListName[2]" type="text" />
<input name="ListName[3]" type="text" />
<input name="ListName[4]" type="text" />
The MVC model binder 8 will always put 5 elements in your list, all String.Empty
. If 7 this is how your View works, your attribute 6 would need to get a bit more complex, such 5 as using Reflection to pull the generic 4 type parameter and comparing each list element 3 with default(T)
or something.
A better alternative 2 is to use jQuery to create the input elements 1 dynamically.
For those who're looking for minimalist 7 examples:
[AttributeUsage(AttributeTargets.Property)]
public sealed class CannotBeEmptyAttribute : RequiredAttribute
{
public override bool IsValid(object value)
{
var list = value as IEnumerable;
return list != null && list.GetEnumerator().MoveNext();
}
}
This is modified code from the 6 accepted answer. It is suitable in the case 5 from the question, and in even more cases, since 4 IEnumerable is higher in System.Collections 3 hierarchy. Additionally, it inherits behavior 2 from RequiredAttribute, so no need in coding 1 it explicitly.
For those that use C# 6.0 (and above) and 1 who are looking for one-liners:
[AttributeUsage(AttributeTargets.Property)]
public sealed class CannotBeEmptyAttribute : RequiredAttribute
{
public override bool IsValid(object value) => (value as IEnumerable)?.GetEnumerator().MoveNext() ?? false;
}
Modified @moudrick implementation for my 3 requirement
Required Validation Attribute 2 for List and checkbox List
[AttributeUsage(AttributeTargets.Property)]
public sealed class CustomListRequiredAttribute : RequiredAttribute
{
public override bool IsValid(object value)
{
var list = value as IEnumerable;
return list != null && list.GetEnumerator().MoveNext();
}
}
If you have checkbox 1 list
[AttributeUsage(AttributeTargets.Property)]
public sealed class CustomCheckBoxListRequiredAttribute : RequiredAttribute
{
public override bool IsValid(object value)
{
bool result = false;
var list = value as IEnumerable<CheckBoxViewModel>;
if (list != null && list.GetEnumerator().MoveNext())
{
foreach (var item in list)
{
if (item.Checked)
{
result = true;
break;
}
}
}
return result;
}
}
Here is my View Model
public class CheckBoxViewModel
{
public string Name { get; set; }
public bool Checked { get; set; }
}
Usage
[CustomListRequiredAttribute(ErrorMessage = "Required.")]
public IEnumerable<YourClass> YourClassList { get; set; }
[CustomCheckBoxListRequiredAttribute(ErrorMessage = "Required.")]
public IEnumerable<CheckBoxViewModel> CheckBoxRequiredList { get; set; }
More Related questions
We use cookies to improve the performance of the site. By staying on our site, you agree to the terms of use of cookies.