这是我之前关于将错误传递回客户端并涉及ModelState的问题的后续,参考此前的提问。
有人成功地使用Nerd Dinner方法实现了Ajax操作吗?因此,Nerd Dinner执行以下更新。
[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);
}
}
使用 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);
}
});
}
Ajax,控制器的“try”部分变为:
try
{
UpdateModel(dinner);
dinnerRepository.Save();
return PartialView("PartialDetails", new { id=dinner.DinnerID });
}
不过catch部分该如何处理呢?
一个简单的错误处理方案是发送一个错误信息:
catch(Exception ex)
{
Response.StatusCode = 500;
return Content("An Error occured.");
//throw ex;
}
但是这个错误消息没有通过MVC内置的健壮模型状态。我考虑了许多选项,但我真正想要的有两点:
- 我想在jQuery的error属性中处理错误。
- 我希望尽可能使用内置的ASP.Net MVC验证逻辑。
这可行吗?如果不行,你知道什么更好的替代方案吗?
非常感谢。
更新 我还没有将此标记为已回答,因为我还没有实现我认为最有效的方法。
我决定不再采用“成功=>发送刷新列表,失败=>发送错误消息”的方法。我这样做是为了减少调用次数,但是刷新列表确实被设置为页面了。尝试同时执行这两个任务会将弹出框紧密绑定到其整体页面上。
我将添加一个自定义jQuery事件,在对话框关闭时刷新主页面列表。本质上,它是观察者模式。我喜欢这个想法,即页面对弹出窗口说“告诉我你完成了”(也就是关闭),而不必告诉弹出窗口原因。它确实需要额外的调用,但我不认为这是一个大问题。
我仍然不确定我喜欢/不喜欢服务器端验证,并且正在考虑仅使用客户端验证。虽然服务器端验证看起来像是一个清晰的分层,但它也有许多问题,包括:
1)它在最后才进行质量检查,而不是在构建的过程中进行检查。类比于制造业的话,这就像一辆汽车到达经销商时才进行测试,而不是在制造过程的各个环节中进行测试。
2)它违反了Ajax的意图。Ajax不仅涉及异步事件的发送,还涉及只发送我需要的内容并只接收我需要的内容。为了提供错误详细信息,将整个模型状态发送回去似乎不符合Ajax的要求。
我想做的是仅使用客户端验证,但可以使用服务器端代码和自定义视图模型告诉客户端如何动态创建这些验证规则。
我还怀疑像IronRuby或IronPython这样的动态语言可能会提供更优雅的解决这些问题的方法,但我可能需要更长时间才能研究这种可能性。