当 Ajax 将参数传递给控制器​​并且模型由于数据注释而无效时如何 return 错误?

How to return errors when Ajax passes parameter to controller and model is invalid due to data annotations?

我有一个 ajax post 调用控制器操作并传递用户(我)输入的参数。

我正在使用数据注释来验证控制器操作中的模型。如果我输入无效值(或没有值)并且 运行 ajax:

问题: return 似乎被忽略,响应为 500(内部服务器错误)。

此时我可以将状态代码设置为 200 来处理成功回调中的错误,但我无法用这个(在控制器操作中)覆盖它:

HttpContext.Response.TrySkipIisCustomErrors = true;
HttpContext.Response.StatusCode = (int)System.Net.HttpStatusCode.OK;

和这个(在 web.config 中):

<httpErrors errorMode="Custom" existingResponse="PassThrough"/>

如果我可以从中检索模型的错误,我也可以return将一个对象连接到错误回调,但从我所读的内容来看,这似乎是不可能的。

我搜索了那么多 post 和博客,这些似乎只适用于找到我不太能应用(技术上或概念上)的相同少数解决方案。

问题: 如何在传递给控制器​​的参数上保留数据注释并强制执行包含模型错误的某种对象的 return?

Ajax:

$('#apply-theme-color-btn').click(function (e) {
    e.preventDefault();

    var themeColor = $('#ThemeColor').val();

    $.ajax({
        url: '/Manage/ChangeThemeColor/' + themeColor,
        type: "POST",
        //dataType: "text",
        data: {"themeColor": themeColor}, //.serialize(),
        beforeSend: function () {
            $('#apply-theme-color-btn').toggleClass('active');
        },
        success: function (data, textStatus, jqXHR) {
            if (data.IsValid) {
                console.log('Success');
            }
            else {
                console.log(data);
            }
        },
        error: function (jqXHR, textStatus, errorThrown) {
            console.log('Error');
        },
        complete: function (jqXHR, textStatus) {
            $('#apply-theme-color-btn').toggleClass('active');
        }
    });
});

控制器:

[HttpPost]
[Route("Manage/ChangeThemeColor/{themeColor:string}")]
public ActionResult ChangeThemeColor(string themeColor, IndexViewModel model) {
    if (!ModelState.IsValid) {
        var result = Json(new { IsValid = false, model = model, errors = ModelState.Values.Where(i => i.Errors.Count > 0) });
        return result;
    }
    else {
        //Do some different stuff
        }
    }

型号:

...
[Required]
[StringLength(7, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 7)]
public string ThemeColor { get; set; }

500 (Internal Server Error) 表示您在控制器方法中抛出异常,在您的情况下是评论中指出的循环引用异常。

要return无效属性的错误集合,请使用

errors = ModelState.Keys.Where(k => ModelState[k].Errors.Count > 0)
    .Select(k => new { propertyName = k, errorMessage = ModelState[k].Errors[0].ErrorMessage })

这将 return 属性 名称和所有无效 属性 值的相关错误消息。

旁注:

  1. url: '/Manage/ChangeThemeColor/' + themeColor, 应该只是 url: '/Manage/ChangeThemeColor', 因为你已经通过了 themeColordata: 选项中(或者更好 @Url.Action("ChangeThemeColor", "Manage")',)
  2. 由于IndexViewModel包含属性ThemeColor,所以没有 在你的方法中需要参数,它应该只是 public ActionResult ChangeThemeColor(IndexViewModel model)
  3. 无需将相同的模型发回给客户 客户端刚刚发送到控制器(从中删除 model = model" return Json() 语句。