在checked复选框中发布表单时,ModelState无效

时间:2012-10-09 19:35:23

标签: asp.net-mvc-4 asp.net-web-api

我遇到以下问题:如果我通过AJAX向api控制器提交包含复选框的选中值的表单,则ModelState对象表示它无效。

先决条件:

  1. Visual Studio 2012
  2. ASP.NET MVC 4 Final
  3. 最新的jQuery和jQuery不显眼的验证内容(版本1.8.2和1.9.0.1)
  4. 重现的步骤:

    1. 为表单创建了一个ViewModel,其中包含Boolean字段:
      public class CheckboxViewModel
      {
      [Display(Name="Test checkbox")]
      public bool TestCheckbox { get; set; }
      }
      
    2. 创建控制器操作,只需准备ViewModel并呈现表单:
      public ActionResult Index()
      {
          return View(new CheckboxViewModel());
      }
      
    3. 使用表单创建视图
      @using (Ajax.BeginForm("Post", "api/Values", null, new AjaxOptions { HttpMethod = "POST" }, new { id = "form" }))
      {
          @Html.ValidationSummary(true)
          @Html.LabelFor(model => model.TestCheckbox)
          @Html.EditorFor(model => model.TestCheckbox)
          @Html.ValidationMessageFor(model => model.TestCheckbox)
          <input type="submit" value="Submit" />
      }
      
    4. 创建Web API操作,检查modelstate是否有效并返回状态代码200,否则返回400:
      public HttpResponseMessage Post(CheckboxViewModel model)
      {
          if (!ModelState.IsValid)
              return new HttpResponseMessage(HttpStatusCode.BadRequest);
          return new HttpResponseMessage(HttpStatusCode.OK);
      }
      
    5. 我已经完成了一些谷歌搜索,我知道复选框的编辑器会呈现额外的隐藏字段,但它似乎没问题,是模型绑定所必需的。 因此,当我取消选中复选框并提交表单时,一切正常,服务器响应状态为200,感谢隐藏字段,我想。但是,当我选中复选框并提交表单时,服务器响应状态为400,这意味着ModelState处于无效状态。在这种情况下,ModelState包含带有空ErrorMessage的错误和以下Exception消息:

      {System.InvalidOperationException: The parameter conversion from type 'System.Collections.Generic.List`1[System.String]' to type 'System.Boolean' failed because no type converter can convert between these types.
         в System.Web.Http.ValueProviders.ValueProviderResult.ConvertSimpleType(CultureInfo culture, Object value, Type destinationType)
         в System.Web.Http.ValueProviders.ValueProviderResult.UnwrapPossibleArrayType(CultureInfo culture, Object value, Type destinationType)
         в System.Web.Http.ValueProviders.ValueProviderResult.ConvertTo(Type type, CultureInfo culture)
         в System.Web.Http.ValueProviders.ValueProviderResult.ConvertTo(Type type)
         в System.Web.Http.ModelBinding.Binders.TypeConverterModelBinder.BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)}
      

      我不知道如何正确处理这个问题。我应该创建自定义模型绑定器?或者我错过了什么? 任何帮助,将不胜感激。感谢。

      我创建了solution来重现我的问题。

      更新:我发现该表单实际上包含值TestCheckbox: trueTestCheckbox:false,所以我认为这可能会影响绑定器并引发异常。仍然没有选择如何解决这个问题。

2 个答案:

答案 0 :(得分:2)

我遇到了使用JavaScript将表单发送到Web API的相同问题。这是一个可以用来解决问题的基本修复。我知道它有点简单甚至丑陋 - 如果你有很多复选框,那就不太实用了。但是,这个想法很简单,可以很容易地扩展以满足您的要求。

在发布表单之前添加它(使用jQuery):

if ($('[name="MyCheckbox"]:checked').length > 0)
    $('[name="MyCheckbox"]:hidden').detach();
else if ($('[name="MyCheckbox"]:hidden').length < 1)
    $('#myForm').append('<input type="hidden" name="MyCheckbox" value="false" />');

// Etc...
$.ajax({ });

如果选中该复选框,则删除隐藏字段,如果未选中复选框并且隐藏字段已被删除,则添加隐藏字段。

请参阅此小提琴:http://jsfiddle.net/Hsfdg/

答案 1 :(得分:1)

我试图实现这个

if ($('[name="MyCheckbox"]:checked').length > 0)
    $('[name="MyCheckbox"]:hidden').detach();
else if ($('[name="MyCheckbox"]:hidden').length < 1)
    $('#myForm').append('<input type="hidden" name="MyCheckbox" value="false" />');

但是当分离隐藏的复选框时,最终会删除模型属性。

Instad将隐藏的chechbox值设置为true,将model属性设置为true,默认值为true,否则为false。

if ($('[name="MyCheckbox"]:checked').length > 0)
    $('[name="MyCheckbox"]:hidden').val(true);