Asp.net mvc 4 在复选框内过帐表单时,ModelState无效

Asp.net mvc 4 在复选框内过帐表单时,ModelState无效,asp.net-mvc-4,asp.net-web-api,Asp.net Mvc 4,Asp.net Web Api,我遇到了以下问题:如果我通过AJAX向api控制器提交一个包含复选框中的选中值的表单,ModelState对象会说它无效 先决条件: Visual Studio 2012 ASP.NET MVC 4最终版 最新的jQuery和jQuery不引人注目的验证内容(版本1.8.2和1.9.0.1) 复制步骤: 已为表单创建ViewModel,其中包含布尔字段: 公共类CheckboxViewModel { [显示(Name=“测试复选框”)] 公共bool TestCheckbox{get;set;

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

先决条件:

  • Visual Studio 2012
  • ASP.NET MVC 4最终版
  • 最新的jQuery和jQuery不引人注目的验证内容(版本1.8.2和1.9.0.1)
  • 复制步骤:

  • 已为表单创建ViewModel,其中包含布尔字段:
    
    公共类CheckboxViewModel
    {
    [显示(Name=“测试复选框”)]
    公共bool TestCheckbox{get;set;}
    }
    
  • 创建的控制器动作,只需准备ViewModel并呈现表单:
    
    公共行动结果索引()
    {
    返回视图(新的CheckboxViewModel());
    }
    
  • 使用表单创建视图
    
    @使用(Ajax.BeginForm(“Post”、“api/Values”、null、新的AjaxOptions{HttpMethod=“Post”}、新的{id=“form”}))
    {
    @Html.ValidationSummary(true)
    @LabelFor(model=>model.TestCheckbox)
    @EditorFor(model=>model.TestCheckbox)
    @Html.ValidationMessageFor(model=>model.TestCheckbox)
    }
    
  • 已创建Web API操作,用于检查modelstate是否有效,并返回状态代码200,否则返回400:
    
    公共HTTPResponseMessagePost(CheckboxViewModel模型)
    {
    如果(!ModelState.IsValid)
    返回新的HttpResponseMessage(HttpStatusCode.BadRequest);
    返回新的HttpResponseMessage(HttpStatusCode.OK);
    }
    
  • 我在谷歌上搜索了一下,我知道复选框编辑器会呈现额外的隐藏字段,但它似乎还可以,并且是模型绑定所必需的。 所以,当我取消选中复选框并提交表单时,一切正常,服务器响应状态为200,我想这要感谢隐藏字段。然而,当我选中复选框并提交表单时,服务器以状态400响应,这意味着ModelState处于无效状态。在这种情况下,ModelState包含带有空ErrorMessage的错误和以下异常消息:
    
    {System.InvalidOperationException:从类型'System.Collections.Generic.List`1[System.String]'到类型'System.Boolean'的参数转换失败,因为没有类型转换器可以在这些类型之间转换。
    of System.Web.Http.ValueProviders.ValueProviderResult.ConvertSimpleType(CultureInfo区域性,对象值,类型destinationType)
    of System.Web.Http.ValueProviders.ValueProviderResult.UnwrapPossibleArrayType(CultureInfo区域性,对象值,类型destinationType)
    of System.Web.Http.ValueProviders.ValueProviderResult.ConvertTo(类型类型,文化信息文化)
    of System.Web.Http.ValueProviders.ValueProviderResult.ConvertTo(类型)
    of System.Web.Http.ModelBinding.Binders.TypeConverterModelBinder.BindModel(HttpActionContext-actionContext,ModelBindingContext-bindingContext)}
    

    我不知道如何妥善处理这件事。我应该创建自定义模型活页夹吗?还是我遗漏了什么? 任何帮助都将不胜感激。谢谢

    我已经创建了一个复制我的问题


    更新:我发现表单实际上包含值
    TestCheckbox:true
    TestCheckbox:false
    ,所以我认为这可能会影响binder,并引发异常。仍然没有办法解决这个问题。

    我在用JavaScript向Web API发送表单时遇到了同样的问题。下面是一个基本的修复方法,可以用来解决这个问题。我知道这有点简单,甚至丑陋——如果你有很多复选框,那就不太实际了。然而,这个想法很简单,可以很容易地扩展以满足您的需求

    在发布表单之前添加以下内容(使用jQuery):

    if($('[name=“MyCheckbox”]:checked')。长度>0)
    $('[name=“MyCheckbox”]:hidden').detach();
    else if($('[name=“MyCheckbox”]:hidden')。长度<1)
    $('#myForm')。追加('');
    //等等。。。
    $.ajax({});
    
    因此,如果选中复选框,则删除隐藏字段;如果未选中复选框且隐藏字段已被删除,则添加隐藏字段


    看到这把小提琴了吗:

    我试图实现这一点

    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" />');
    

    谢谢你的回复。是的,这是可行的,尽管额外的jquery内容无助于编写干净的代码。:)我会接受你的回答,但我最终放弃了EditorFor,使用了原始html,因为我决定使用knockoutjs和干净的javascript/jquery。 public ActionResult Index() { return View(new CheckboxViewModel()); } @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" /> } public HttpResponseMessage Post(CheckboxViewModel model) { if (!ModelState.IsValid) return new HttpResponseMessage(HttpStatusCode.BadRequest); return new HttpResponseMessage(HttpStatusCode.OK); } {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)}
    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({ });
    
    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" />');
    
    if ($('[name="MyCheckbox"]:checked').length > 0)
        $('[name="MyCheckbox"]:hidden').val(true);