模型绑定问题和 Ajax 表单未捕获模型错误

Issue with Model Binding and Ajax form not catching model errors

我有一个问题,我不确定如何解决。我有一个普通的 .net MVC 5 应用程序,我已经编写了一个自定义默认模型绑定程序来处理不引人注目的验证并捕获 HttpRequestValidationException 错误。

模型活页夹如下所示:

public class DefaultModelBinderWithHtmlValidation : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        try
        {
            return base.BindModel(controllerContext, bindingContext);
        }
        catch (HttpRequestValidationException)
        {
            Trace.TraceWarning("Ilegal characters were found in field {0}", bindingContext.ModelMetadata.DisplayName ?? bindingContext.ModelName);
            bindingContext.ModelState.AddModelError(bindingContext.ModelName, string.Format("Ilegal characters were found in field {0}.  No HTML is allowed.", bindingContext.ModelMetadata.DisplayName ?? bindingContext.ModelName));
        }

        //Cast the value provider to an IUnvalidatedValueProvider, which allows to skip validation
        IUnvalidatedValueProvider provider = bindingContext.ValueProvider as IUnvalidatedValueProvider;
        if (provider == null) return null;

        //Get the attempted value, skiping the validation
        var result = provider.GetValue(bindingContext.ModelName, skipValidation: true);
        Debug.Assert(result != null, "result is null");

        return result.AttemptedValue;
    }
}

它非常适合普通绑定和视图与控制器之间的 posts。但是,我注意到当我使用包含 Ajax.BeginForm 的表单时,事情不会按预期工作。

我的控制器很简单:

[HttpPost]
    public ActionResult Index(HomeViewModel model)
    {
        if (ModelState.IsValid)
        {
            Thread.Sleep(3000);
            return View(model);
        }
        else
        {
            return View(model);
        }

    }

在正常的非 ajax 形式 post 中,模型返回错误并按预期显示。在我的 ajax post 中,控制器获取有错误的模型并将其传递回视图,但即使模型字段有错误,它也不会被修饰或突出显示。

我知道错误的字段在视图中如下所示:

          <div class="form-group col-sm-3 col-xs-offset-1">
                @Html.LabelFor(model => model.LastName, htmlAttributes: new { @class = "control-label" })
                @Html.EditorFor(model => model.LastName, new { htmlAttributes = new { @class = "form-control", aria_required = "true", @style = "text-transform:uppercase" } })
                @Html.ValidationMessageFor(model => model.LastName, "", new { @class = "text-danger" })
            </div>

正常工作和不正常工作之间的唯一区别是将 Html.BeginForm 更改为 Ajax.BeginForm

我的 ajax 选项如下所示:

@using (Ajax.BeginForm("Index", "Home", null, new AjaxOptions
{
    HttpMethod = "POST",
    InsertionMode = InsertionMode.Replace,
    OnBegin = "onBegin",
    OnComplete = "onComplete",
    OnFailure = "showError"
}, new { id = "HomeForm" })) // set new Id name for  Form

我的功能也确实做的不多:

 function onBegin() {
     $("#homeModal").toggle();
        }
function onComplete() {
    $("#homeModal").toggle();
      }
function showError(error) {
    alert('we have an error.');
    alert(error.responseText);
}

我环顾四周,虽然我看到其他 AJAX 相关的 posts,但我似乎找不到以这种方式处理此问题的方法。如果有,请指出它们,我为没有抓住它们而道歉。我确定我遗漏了一些简单的东西。

在此先感谢您的帮助。

-戴夫

Stephen 的解决方案效果最好。

"
在您的表单中包含一个 <div id="formcontent">,然后包含 UpdateTargetId = "formcontent" 并让方法 return 成为仅包含表单控件的部分视图,因此您可以使用部分 [=] 更新 DOM 20=]ing – Stephen Muecke 1 小时前

就是这样!