Model Binding和Ajax形式的问题没有捕获模型错误

时间:2017-11-09 21:43:20

标签: c# .net asp.net-mvc asp.net-ajax model-binding

我有一个问题,我不知道如何解决。我有一个普通的.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;
    }
}

它对于视图和控制器之间的正常绑定和帖子非常有用。但是,我注意到当我使用包含 Ajax.BeginForm 的表单时,事情无法正常工作。

我的控制器很简单:

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

    }

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

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

          <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相关的帖子但我似乎找不到以这种方式处理这个问题的帖子。如果有,请指出他们,我为没有抓住他们而道歉。我确信我错过了一些简单的事情。

提前感谢您的任何帮助。

-Dave

1 个答案:

答案 0 :(得分:0)

斯蒂芬的解决方案效果最佳。

&#34;
在表单中包含<div id="formcontent">,然后包含UpdateTargetId = "formcontent"并让方法返回仅包含表单控件的局部视图,这样您就可以使用返回的部分更新DOM - Stephen Muecke 1小时前&#34;

那就是它!