2010-05-11 25 views
13

Làm cách nào để hiển thị lỗi ModelState được trả về bởi JSON?Làm thế nào để đọc lỗi mô hình khi được trả về bởi Json?

tôi muốn làm một cái gì đó như thế này:

if (!ValidateLogOn(Name, currentPassword)) 
    { 
     ModelState.AddModelError("_FORM", "Username or password is incorrect."); 

     //Return a json object to the javascript 
     return Json(new { ModelState }); 
    } 

gì phải mã của tôi trong giao diện để đọc các lỗi ModelState và hiển thị chúng?

mã thực tế của tôi trong giao diện để đọc các giá trị JSON là như sau:

function createCategoryComplete(e) { 
    var obj = e.get_object(); 
    alert(obj.Values); 
} 
+0

Có một giải pháp ở đây: http://stackoverflow.com/questions/2845852/asp-net-mvc-how-to-convert-modelstate-errors-to-json –

Trả lời

-8

Nếu bạn đang trở về JSON, bạn không thể sử dụng ModelState. Mọi thứ mà khung nhìn cần phải được chứa bên trong chuỗi JSON. Vì vậy, thay vì thêm lỗi vào ModelState, bạn có thể thêm nó vào mô hình bạn đang tuần tự hóa:

public ActionResult Index() 
{ 
    return Json(new 
    { 
     errorControl = "_FORM", 
     errorMessage = "Username or password is incorrect.", 
     someOtherProperty = "some other value" 
    }); 
} 
+1

Không hiểu tại sao ModelState lại không thể được dùng. Ví dụ.mô hình chất kết dính có thể đặt lỗi cho ModelState, bộ lọc hành động, vv; nếu chúng ta không sử dụng ModelState, người dùng thậm chí sẽ không biết về chúng. – queen3

+0

ModelState không tuần tự hóa. Tôi gặp lỗi tham chiếu lưu hành. –

47

Đây là mã dự thảo nhưng ý tưởng tương tự cũng phù hợp với tôi trong quá trình sản xuất. Ý tưởng chính ở đây là các lỗi Json có tên thẻ được xác định trước, mà không có đối tượng bình thường nào sẽ có. Đối với lỗi xác thực lỗi HTML được tạo lại bằng JavaScript (cả phần tóm tắt và phần tử biểu mẫu nổi bật).

Server side:

public static JsonResult JsonValidation(this ModelStateDictionary state) 
    { 
    return new JsonResult 
    { 
     Data = new 
      { 
       Tag = "ValidationError", 
       State = from e in state 
         where e.Value.Errors.Count > 0 
         select new 
         { 
         Name = e.Key, 
         Errors = e.Value.Errors.Select(x => x.ErrorMessage) 
          .Concat(e.Value.Errors.Where(x => x.Exception != null).Select(x => x.Exception.Message)) 
         } 
      } 
    }; 
    } 

    in action: 
    if (!ModelState.IsValid && Request.IsAjaxRequest()) 
     return ModelState.JsonValidation(); 

phía Chủ đầu tư:

function getValidationSummary() { 
    var el = $(".validation-summary-errors"); 
    if (el.length == 0) { 
     $(".title-separator").after("<div><ul class='validation-summary-errors ui-state-error'></ul></div>"); 
     el = $(".validation-summary-errors"); 
    } 
    return el; 
} 

function getResponseValidationObject(response) { 
    if (response && response.Tag && response.Tag == "ValidationError") 
     return response; 
    return null; 
} 

function CheckValidationErrorResponse(response, form, summaryElement) { 
    var data = getResponseValidationObject(response); 
    if (!data) return; 

    var list = summaryElement || getValidationSummary(); 
    list.html(''); 
    $.each(data.State, function(i, item) { 
     list.append("<li>" + item.Errors.join("</li><li>") + "</li>"); 
     if (form && item.Name.length > 0) 
     $(form).find("*[name='" + item.Name + "']").addClass("ui-state-error"); 
    }); 
} 

$.ajax(... function(response) { 
    CheckValidationErrorResponse(xhr.responseText); }); 
+2

Thật tuyệt vời! Mã bạn cung cấp cũng cực kỳ di động. Điều duy nhất tôi cần thay đổi là "$ (". Title-separator ")" để phù hợp với DOM của tôi. –

+0

bạn đặt thành gì: summaryElement ?? tôi không thấy rằng bất cứ nơi nào trong mã của bạn. – leora

+1

summaryElement được chuyển đến CheckValidationErrorResponse nếu tôi muốn hiển thị lỗi ở vị trí không mặc định - ví dụ: trong biểu mẫu chỉnh sửa jqGrid. Đây là phần tử/bộ chọn jquery của ul/div/etc có nội dung sẽ được thay thế bằng thẻ li có lỗi. Trong mã của tôi ở trên bạn sẽ vượt qua nó CheckValidationErrorResponse trong $ .ajax callback. – queen3

2

đây là một tinh chỉnh nhỏ để mã phía khách hàng queen3 của mà xử lý các thông điệp xác nhận cụ thể, và tạo ra một tài liệu tương tự như tạo ra bởi MVC3 :

function getValidationSummary() { 
    var $el = $(".validation-summary-errors > ul"); 
    if ($el.length == 0) { 
     $el = $("<div class='validation-summary-errors'><ul></ul></div>") 
       .hide() 
       .insertBefore('fieldset:first') 
       .find('ul'); 
    } 
    return $el; 
} 
function getResponseValidationObject(response) { 
    if (response && response.Tag && response.Tag == "ValidationError") 
     return response; 
    return null; 
} 
function isValidationErrorResponse(response, form, summaryElement) { 
    var $list, 
     data = getResponseValidationObject(response); 
    if (!data) return false; 
    $list = summaryElement || getValidationSummary(); 
    $list.html(''); 
    $.each(data.State, function (i, item) { 
     var $val, lblTxt, errorList =""; 
     if (item.Name) { 
      $val = $(".field-validation-valid,.field-validation-error") 
         .first("[data-valmsg-for=" + item.Name + "]") 
         .removeClass("field-validation-valid") 
         .addClass("field-validation-error"); 
      $("input[name=" + item.Name + "]").addClass("input-validation-error") 
      lblTxt = $("label[for=" + item.Name + "]").text(); 
      if (lblTxt) { lblTxt += ": "; } 
     } 
     if ($val.length) { 
      $val.text(item.Errors.shift()); 
      if (!item.Errors.length) { return; } 
     } 
     $.each(item.Errors, function (c,val) { 
      errorList += "<li>" + lblTxt + val + "</li>"; 
     }); 
     $list.append(errorList); 
    }); 
    if ($list.find("li:first").length) {$list.closest("div").show(); } 
    return true; 
} 
+0

Cảm ơn Brent. Hai đề xuất - $ .first() không chấp nhận đối số, có nên là $ .filter() không? Sau đó $ ("input [name = ...]") không bao gồm lựa chọn, textarea, vv - có thể được thay đổi thành $ ("* [name = ...]")? – DGreen

1

Xem bên dưới để biết mã với một vài sửa đổi đối với câu trả lời của Brent. CheckValidationErrorResponse tìm kiếm Tóm tắt Xác thực bất kể nó ở trạng thái hợp lệ hay không hợp lệ, và chèn nó nếu không tìm thấy. Nếu các lỗi xác nhận được tìm thấy trong phản hồi, nó áp dụng lớp xác thực-tóm tắt lỗi cho Tóm tắt, nếu không nó sẽ áp dụng tính hợp lệ-tóm tắt-hợp lệ. Nó giả định CSS có mặt để kiểm soát khả năng hiển thị của Tóm tắt.

Mã sẽ xóa các trường hợp lỗi xác thực trường hiện tại và áp dụng lại chúng cho các lỗi được tìm thấy trong phản hồi.

function getValidationSummary(form) { 
    var $summ = $(form).find('*[data-valmsg-summary="true"]'); 

    if ($summ.length == 0) 
    { 
    $summ = $('<div class="validation-summary-valid" data-valmsg-summary="true"><ul></ul></div>'); 
     $summ.appendTo(form); 
    } 

    return $summ; 
} 

function getValidationList(summary) { 
    var $list = $(summary).children('ul'); 

    if ($list.length == 0) { 
     $list = $('<ul></ul>'); 
     $list.appendTo(summary); 
    } 

    return $list; 
} 

function getResponseValidationErrors(data) { 
    if (data && data.ModelErrors && data.ModelErrors.length > 0) 
     return data.ModelErrors; 
    return null; 
} 

function CheckValidationErrorResponse(data, form, summaryElement) { 
    var errors = getResponseValidationErrors(data); 
    var $summ = summaryElement || getValidationSummary(form); 
    var $list = getValidationList($summ); 

    $list.html(''); 

    $(form).find(".field-validation-error") 
      .removeClass("field-validation-error") 
      .addClass("field-validation-valid"); 

    if (!errors) 
    { 
     $summ.removeClass('validation-summary-errors').addClass('validation-summary-valid'); 
     return false; 
    } 

    $.each(errors, function (i, item) { 
     var $val, $input, errorList = ""; 
     if (item.Name) { 
      $val = $(form).find(".field-validation-valid, .field-validation-error") 
          .filter("[data-valmsg-for=" + item.Name + "]") 
          .removeClass("field-validation-valid") 
          .addClass("field-validation-error"); 

      $input = $(form).find("*[name='" + item.Name + "']"); 

      if (!$input.is(":hidden") && !$val.length) 
      { 
       $input.parent().append("<span class='field-validation-error' data-valmsg-for='" + item.Name + "' data-valmsg-replace='false'>*</span>"); 
      } 

      $input.addClass("input-validation-error"); 
     } 

     $.each(item.Errors, function (c, err) { 
      errorList += "<li>" + err + "</li>"; 
     }); 

     $list.append(errorList); 
    }); 

    $summ.removeClass('validation-summary-valid').addClass('validation-summary-errors'); 
    return true; 
} 
3

Tại sao không trả lại đối tượng gốc ModelState cho khách hàng, và sau đó sử dụng jQuery để đọc các giá trị. Đối với tôi có vẻ đơn giản hơn nhiều, và sử dụng các cấu trúc dữ liệu chung (.net của ModelState)

C#:

return Json(ModelState); 

js:

var message = ""; 
if (e.response.length > 0) { 
    $.each(e.response, function(i, fieldItem) { 
     $.each(fieldItem.Value.Errors, function(j, errItem) { 
      message += errItem.ErrorMessage; 
     }); 
     message += "\n"; 
    }); 
    alert(message); 
} 
0

C#

public class ValidateModelAttribute : ActionFilterAttribute 
    { 
     public override void OnActionExecuting(HttpActionContext actionContext) 
     { 
      if (actionContext.ModelState.IsValid == false) 
      { 
       actionContext.Response = actionContext.Request.CreateErrorResponse(
        HttpStatusCode.BadRequest, actionContext.ModelState); 
      } 
     } 
    } 

Javascript

$.ajax({ 
     type: "GET", 
     url: "/api/xxxxx", 
     async: 'false', 
     error: function (xhr, status, err) { 
      if (xhr.status == 400) { 
       DisplayModelStateErrors(xhr.responseJSON.ModelState); 
      } 
     }, 
.... 


function DisplayModelStateErrors(modelState) { 
    var message = ""; 
    var propStrings = Object.keys(modelState); 

    $.each(propStrings, function (i, propString) { 
     var propErrors = modelState[propString]; 
     $.each(propErrors, function (j, propError) { 
      message += propError; 
     }); 
     message += "\n"; 
    }); 

    alert(message); 
}; 
Các vấn đề liên quan