4

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

先决条件:

  1. 视觉工作室 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)}

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

我创建了重现我的问题的解决方案。

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

4

2 回答 2

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/

于 2012-10-16T10:23:16.163 回答
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 会导致将模型属性设置为 true 预期的值,否则默认为 false。

if ($('[name="MyCheckbox"]:checked').length > 0)
    $('[name="MyCheckbox"]:hidden').val(true);
于 2012-11-01T03:43:00.790 回答