2010-05-11 71 views
13

如何显示JSON返回的ModelState错误?如何在Json返回时读取模型状态错误?

我想要做这样的事情:

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

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

什么一定是我的视图代码读取的ModelState错误,并显示它们?

我在视图中实际的代码读取JSON值如下:

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

这里有一个解决方案:http://stackoverflow.com/questions/2845852/asp-net-mvc-how-to-convert-modelstate-errors-to-json – 2012-11-22 15:26:40

回答

-8

如果你正在返回JSON,你不能使用的ModelState。视图需要的所有东西都应该包含在JSON字符串中。因此,而不是将错误的ModelState中,你可以把它添加到您的序列化的模型:

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

不明白为什么ModelState不能使用。例如。模型粘合剂可以将错误放入模型状态,动作过滤器等​​;如果我们不使用ModelState,用户甚至不会知道它们。 – queen3 2010-05-11 08:01:32

+0

ModelState不会序列化。我收到了循环引用错误。 – 2014-02-04 10:44:01

47

这是准则草案,但同样的想法在生产中对我的作品。 这里的主要想法是Json错误有预定义的标签名称,没有普通的对象会有。对于错误验证错误使用JavaScript重新创建HTML(高亮总结和表单元素高亮显示)。

服务器端:

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

客户端:

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

做得很好!您提供的代码也非常便于携带。我唯一需要改变的是“$(”。title-separator“)”来匹配我的DOM。 – 2010-12-08 00:53:52

+0

你会做什么:summaryElement ??我没有看到你的代码中的任何地方。 – leora 2011-04-20 05:40:41

+1

summary如果我想在非默认位置显示错误,则将元素传递给CheckValidationErrorResponse - 例如在jqGrid编辑表单中。这是一个ul/div/etc的jquery元素/选择器,其内容将被替换为带有错误的li标签。在我上面的代码中,您可以在$ .ajax回调中传递CheckValidationErrorResponse。 – queen3 2011-05-17 07:18:44

2

这是一个很小的调整,以queen3的客户端代码处理特定的验证消息,并创建一个类似的文件,以通过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

谢谢布伦特。几个建议 - $ .first()不接受参数,它应该是$ .filter()吗?然后$(“input [name = ...]”)排除select,textarea等 - 可以更改为$(“* [name = ...]”)? – DGreen 2013-05-24 11:05:29

1

请参阅下面的代码,对布伦特答案进行一些修改。 CheckValidationErrorResponse查找验证摘要,无论其处于有效还是无效状态,并在未找到时插入。如果在响应中发现验证错误,它将validation-summary-errors类应用于摘要,否则它将应用validation-summary-valid。它假定CSS存在以控制摘要的可见性。

该代码清除现有的field-validation-error实例,并重新应用它们以查找响应中发现的错误。

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

为什么不将原始ModelState对象返回给客户端,然后使用jQuery读取值。对我来说,它看起来更简单,并采用通用的数据结构(.NET的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); 
}; 
相关问题