我遇到以下问题:如果我通过AJAX向api控制器提交包含复选框的选中值的表单,则ModelState对象表示它无效。
先决条件:
重现的步骤:
public class CheckboxViewModel
{
[Display(Name="Test checkbox")]
public bool TestCheckbox { get; set; }
}
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);
}
我已经完成了一些谷歌搜索,我知道复选框的编辑器会呈现额外的隐藏字段,但它似乎没问题,是模型绑定所必需的。
因此,当我取消选中复选框并提交表单时,一切正常,服务器响应状态为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: true
和TestCheckbox:false
,所以我认为这可能会影响绑定器并引发异常。仍然没有选择如何解决这个问题。
答案 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);