在ASP.Net MVC中,ModelState可以与ajax更新一起使用吗?

Joh*_*ohn 9 error-handling asp.net-mvc jquery

这是我之前关于将错误传递回客户端的前一个问题的后续内容,但也与ModelState有关.

有没有人成功使用过Nerd Dinner方法,但是使用Ajax?因此,书呆子晚餐会更新.

[AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Edit(int id, FormCollection formValues) 
{
    Dinner dinner = dinnerRepository.GetDinner(id);
    try 
    {
        UpdateModel(dinner);
        dinnerRepository.Save();
        return RedirectToAction("Details", new { id=dinner.DinnerID });
    }
    catch 
    {
        foreach (var issue in dinner.GetRuleViolations()) {
        ModelState.AddModelError(issue.PropertyName, issue.ErrorMessage);
    }
        return View(dinner);
    }
}
Run Code Online (Sandbox Code Playgroud)

使用jQuery $ .ajax

function hijack(form, callback, errorFunction, format) {
    $.ajax({
        url: form.action,
        type: form.method,
        dataType: format,
        data: $(form).serialize(),
        success: callback,
        error: function(xhr, textStatus, errorThrown) {
            errorFunction(xhr, textStatus, errorThrown);
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

Ajax,控制器的"尝试"部分

    try 
{
    UpdateModel(dinner);
    dinnerRepository.Save();
    return PartialView("PartialDetails", new { id=dinner.DinnerID });
}
Run Code Online (Sandbox Code Playgroud)

,但是你对捕获部分做了什么?

发送错误的简单错误处理解决方案将是

catch(Exception ex)
{
    Response.StatusCode = 500;                
    return Content("An Error occured.");
    //throw ex;
}
Run Code Online (Sandbox Code Playgroud)

,但这并没有通过 MVC内置的健壮的模型状态.我想到了很多选择,但我真的想要两件事:

  1. 我希望在jQuery的错误属性中处理错误.
  2. 我想尽可能使用内置的ASP.Net MVC验证逻辑.

这可能吗?如果没有,您知道的最佳替代方案是什么?

非常感谢.

更新 我还没有将此标记为已回答,因为我还没有实现我认为最有效的方法.

我已经决定我真的不喜欢成功=>发送刷新列表,失败=>发送我正在采取的错误消息方法.我这样做是为了减少调用次数,但是刷新的列表实际上是设置在页面上的.尝试两者都将弹出窗口紧紧绑定到整个页面.

我将在对话框关闭时添加自定义jQuery事件刷新母版页列表.从本质上讲,它是观察者模式.我喜欢这个页面对弹出窗口说"告诉我你什么时候完成"(也就是关闭)的想法,而不必告诉弹出窗口为什么.它确实需要额外的电话,但我不认为这是一个大问题.

我仍然不确定我喜欢/不喜欢服务器端验证,我正在考虑进行客户端验证.虽然服务器端验证看起来像干净的分层,但它也有许多问题,包括:

1)它将质量检查放在最后,而不是开头.与制造业类比的是一辆汽车,当它到达经销商时进行测试,而不是在正在建造的过程中进行测试.
2)它违反了Ajax的意图.Ajax不仅仅是发送异步事件,还涉及仅发送我需要的内容并仅接收我需要的东西.发送回整个模型状态以提供错误详细信息似乎与Ajax无关.

我正在考虑做的是仅进行客户端验证,但可以使用服务器代码和自定义视图模型来告诉客户端如何动态创建这些验证规则.

我还怀疑像IronRuby或IronPython这样的动态语言可能会提供一种更优雅的方法来解决这些问题,但在我研究这种可能性之前可能还需要一段时间.

JOB*_*OBG 4

如果我明白你想要做什么,我的第一个答案将是“否”,你不能使用模型状态,因为它是通过 Ajax 请求来使用的。

您也许能够模拟该ModelState行为,以显示错误:

  1. 通过 JSON传递List<KeyValuePair<string,string>>(属性,消息)(这将要求您将 modelErrors 从 传递到ModelState新结构)并通过 JS/jQuery 进行验证摘要的 HTML 构造(我认为这是过度的解决方案)。

  2. 如果您要访问服务器,并且出现任何错误,只需渲染部分Html.ValidationSummary(),通过 JSON 传递它,并将其添加到表单中。如果一切正常,只需返回PartialDetails视图并替换实际内容即可。这将需要某种状态参数,以便您知道 ajax 回调中服务器返回的内容。

编辑:最后一个选项听起来不错但很棘手,因为您需要以字符串形式返回部分视图JSONResult。以下是有关该 hack 的问题和解决方案:How to render an ASP.NET MVC view as a string?

就我个人而言,我认为使用 error 属性根本没有任何好处。我只是在非常特定的情况下使用它,例如超时错误和服务器异常,而不是应用程序异常。

编辑:

使用 JSON:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(int id, FormCollection formValues)
{
    Dinner dinner = dinnerRepository.GetDinner(id);
    try
    {
        UpdateModel(dinner);
        dinnerRepository.Save();
        return Json(new 
        {
            result = "success",
            html = this.RenderToString("PartialDetails", dinner) 
        });

    }
    catch
    {
        foreach (var issue in dinner.GetRuleViolations())
        {
            ModelState.AddModelError(issue.PropertyName, issue.ErrorMessage);
        }
        return Json(new
        {
            result = "failed",
            html = this.RenderToString("PartialEdit", dinner)
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

这里的result参数将让您知道在每种情况下要执行什么操作,只需在回调中检查它即可。