2011-11-22 29 views
11

Tôi có thể thấy rằng ModelState.Values[x].Errors của tôi được điền chính xác với hai lỗi xác thực cho một thuộc tính duy nhất.Cách hiển thị nhiều lỗi xác thực với @ Html.ValidationMessageFor?

Nếu tôi sử dụng @Html.ValidationSummary() theo quan điểm của tôi, nó hiển thị chính xác cả lỗi .... mặc dù ở đầu trang và không bên cạnh đầu vào vi phạm.

Sử dụng @Html.ValidationMessageFor(model => model.MyProperty) hiển thị lỗi đầu tiên chỉ cho thuộc tính đó!

Làm cách nào để hiển thị cả hai lỗi, bên cạnh mục nhập phù hợp?

Trả lời

10

Một giải pháp là triển khai phương pháp mở rộng của riêng bạn trên HtmlHelper có điều gì đó khác với hành vi ValidationMessageFor mặc định. Phương thức @ Html.ValidationMessagesFor mẫu dưới đây sẽ nối nhiều thông báo lỗi đã được thêm vào ModelState trong khi xác thực phía máy chủ (chỉ).

public static MvcHtmlString ValidationMessagesFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes = null) 
{ 
    var propertyName = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData).PropertyName; 
    var modelState = htmlHelper.ViewData.ModelState; 

    // If we have multiple (server-side) validation errors, collect and present them. 
    if (modelState.ContainsKey(propertyName) && modelState[propertyName].Errors.Count > 1) 
    { 
     var msgs = new StringBuilder(); 
     foreach (ModelError error in modelState[propertyName].Errors) 
     { 
      msgs.AppendLine(error.ErrorMessage); 
     } 

     // Return standard ValidationMessageFor, overriding the message with our concatenated list of messages. 
     return htmlHelper.ValidationMessageFor(expression, msgs.ToString(), htmlAttributes as IDictionary<string, object> ?? htmlAttributes); 
    } 

    // Revert to default behaviour. 
    return htmlHelper.ValidationMessageFor(expression, null, htmlAttributes as IDictionary<string, object> ?? htmlAttributes); 
} 

Điều này rất hữu ích nếu bạn có xác thực doanh nghiệp tùy chỉnh bạn đang áp dụng trên một bộ sưu tập thuộc mô hình của bạn (ví dụ, tổng kiểm tra chéo) hoặc kiểm tra toàn bộ mô hình.

Một ví dụ sử dụng này, nơi một bộ sưu tập của Order.LineItems được xác nhận server-side:

@using MyHtmlHelperExtensions // namespace containing ValidationMessagesFor 
@using (Html.BeginForm()) 
{ 
    @Html.LabelFor(m => m.LineItems) 
    <ul> 
     @Html.EditorFor(m => m.LineItems) 
    </ul> 
    @Html.ValidationMessagesFor(m => m.LineItems) 
} 
+0

đẹp giải pháp. Điều này có hoạt động với chế độ xem lồng nhau với chế độ xem không? Tôi phải thêm các thông tin sau: 'var relativePropertyName = ExpressionHelper.GetExpressionText (expression);' 'var propertyName = String.Format (" {0} {2} {1} ", htmlHelper.ViewContext.ViewData.TemplateInfo. HtmlFieldPrefix, relativePropertyName, (String.IsNullOrWhiteSpace (relativePropertyName)? String.Empty: ".")); ' – Fiddles

+0

Cách đơn giản để làm cho nó hoạt động với các khung nhìn lồng nhau là: propertyName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName (propertyName) –

+0

Câu trả lời xuất sắc, và nó hoạt động. Ngoại trừ cả hai lỗi của tôi đều nằm trên cùng một dòng. Tôi cần mỗi thông báo lỗi để được trên dòng riêng của nó. Với một thẻ
ở giữa ví dụ – theB3RV

3

Câu trả lời Dave A-W cung cấp là cơ bản đúng nhưng sẽ không làm việc trong tất cả các trường. Để có được tên thuộc tính đúng mã nguồn của MVC 3 sử dụng:

var propertyName = ExpressionHelper.GetExpressionText(expression); 

này sẽ chăm sóc của bất kỳ tiền tố trong các dữ liệu hình thức

Các vấn đề liên quan