2011-06-21 52 views
23

Có thể đặt thuộc tính [Bắt buộc] vào thuộc tính Danh sách <> không?Thuộc tính bắt buộc trên thuộc tính danh sách chung

Tôi liên kết với danh sách chung trên POST và đã tự hỏi liệu tôi có thể tạo ModelState.IsValid() không nếu thuộc tính có 0 mục trong đó?

+0

Nếu bạn thay đổi mô hình của bạn để sử dụng một mảng thay vì một danh sách, bạn có thể sử dụng [MinLengthAttribute ] (https://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.minlengthattribute%28v=vs.110%29.aspx) – janv8000

Trả lời

27

Thêm thuộc tính Required vào thuộc tính kiểu danh sách không thực sự làm những gì bạn muốn. Sẽ khiếu nại nếu danh sách không được tạo ra, nhưng sẽ không phàn nàn nếu danh sách tồn tại với 0 mục trong đó.

Tuy nhiên, nó phải là đủ dễ dàng để lấy được thuộc tính chú thích dữ liệu của bạn và làm cho nó kiểm tra danh sách cho Count> 0. Một cái gì đó như thế này (không được thử nghiệm chưa):

[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:

Bạn cũng sẽ phải cẩn thận cách bạn ràng buộc danh sách trong chế độ xem của mình. Ví dụ, nếu bạn liên kết một List<String> đến một cái nhìn như thế này:

<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" /> 

Các mô hình MVC binder sẽ luôn đặt 5 yếu tố trong danh sách của bạn, tất cả String.Empty. Nếu đây là cách Chế độ xem của bạn hoạt động, thuộc tính của bạn sẽ cần phức tạp hơn một chút, chẳng hạn như sử dụng Reflection để lấy thông số loại chung và so sánh từng phần tử danh sách với default(T) hoặc thứ gì đó.

Một lựa chọn tốt hơn là sử dụng jQuery để tạo các yếu tố đầu vào động.

+0

Tôi không cho rằng bạn có thể [xây dựng trên bản chỉnh sửa đó] (https://stackoverflow.com/questions/45201531/cant-force-listint-to-be-required)? – Sinjai

+0

Tôi không chắc chắn bạn đang chỉnh sửa nội dung gì ... liên kết của bạn sẽ chuyển sang câu hỏi. –

+0

Vâng, câu hỏi là (có khả năng - đó là một phần những gì tôi đang hỏi) có liên quan. – Sinjai

20

Đối với những người đang tìm kiếm ví dụ nhỏ gọn:

[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(); 
    } 
} 

này được sửa đổi mã từ câu trả lời chấp nhận. Nó phù hợp trong trường hợp từ câu hỏi, và trong nhiều trường hợp hơn, vì IEnumerable cao hơn trong hệ thống phân cấp System.Collections. Ngoài ra, nó kế thừa hành vi từ RequiredAttribute, vì vậy không cần phải mã hóa nó một cách rõ ràng.

+0

Giải pháp chung nhất, Cảm ơn! –

1

Modified thực hiện @moudrick cho yêu cầu của tôi

buộc Validation Thuộc tính cho Danh sách và hộp kiểm Danh sách

[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(); 
    } 
} 

Nếu bạn có danh sách hộp kiểm

[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; 
    } 
} 

Đây là Xem các mẫu của tôi

public class CheckBoxViewModel 
{   
    public string Name { get; set; } 
    public bool Checked { get; set; } 
} 

Cách sử dụng

[CustomListRequiredAttribute(ErrorMessage = "Required.")] 
public IEnumerable<YourClass> YourClassList { get; set; } 

[CustomCheckBoxListRequiredAttribute(ErrorMessage = "Required.")] 
public IEnumerable<CheckBoxViewModel> CheckBoxRequiredList { get; set; } 
2

Đối với những người sử dụng C# 6.0 và người đang tìm kiếm một lớp lót:

[AttributeUsage(AttributeTargets.Property)] 
public sealed class CannotBeEmptyAttribute : RequiredAttribute 
{ 
    public override bool IsValid(object value) => (value as IEnumerable)?.GetEnumerator().MoveNext() ?? false; 
} 
Các vấn đề liên quan