【问题标题】:ModelState is invalid when posting a form within checked checkbox在选中的复选框中发布表单时,ModelState 无效
【发布时间】:2012-10-09 19:35:23
【问题描述】:

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

先决条件:

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

重现步骤:

  1. 为表单创建了一个 ViewModel,包含布尔字段:
    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 操作检查模型状态是否有效并返回状态代码 200,否则返回 400:
    public HttpResponseMessage Post(CheckboxViewModel model)
    {
        if (!ModelState.IsValid)
            return new HttpResponseMessage(HttpStatusCode.BadRequest);
        return new HttpResponseMessage(HttpStatusCode.OK);
    }
    

我做了一些谷歌搜索,我知道复选框的编辑器会呈现额外的隐藏字段,但它似乎没问题,并且是模型绑定所必需的。 因此,当我取消选中复选框并提交表单时一切正常,服务器响应状态为 200,这要归功于隐藏字段,我想。但是,当我选中复选框并提交表单时,服务器以状态 400 响应,这意味着 ModelState 处于无效状态。在这种情况下,ModelState 包含带有空 ErrorMessage 的错误和以下异常消息:

{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,所以我认为这可能会影响活页夹并引发异常。仍然没有办法解决这个问题。

【问题讨论】:

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


    【解决方案1】:

    我在使用 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/

    【讨论】:

    • 感谢您的回复。是的,这行得通,尽管额外的 jquery 内容无助于编写干净的代码。 :) 我会接受你的回答,但我最终放弃了 EditorFor 并使用原始 html,因为我决定使用 knockoutjs 并清理 javascript/jquery。
    【解决方案2】:

    我试图实现这个

    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 将隐藏的复选框值设置为 true 会导致将模型属性设置为 true 预期的值,否则默认为 false。

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

    【讨论】:

      猜你喜欢
      • 2015-03-19
      • 2013-10-14
      • 2013-05-21
      • 1970-01-01
      • 2019-09-04
      • 1970-01-01
      • 1970-01-01
      • 2018-12-16
      • 1970-01-01
      相关资源
      最近更新 更多