ModelState недействителен при отправке флажка в установленном флажке

У меня возникла следующая проблема: если я передам форму, содержащую проверочное значение в флажке, в контроллер api через AJAX, объект ModelState говорит, что он недействителен.

Предпосылки:

  • Visual Studio 2012
  • Фирменный стиль ASP.NET MVC 4
  • Последние jQuery и jQuery ненавязчивые материалы проверки (версии 1.8.2 и 1.9.0.1)

Шаги для воспроизведения:

  • Создал ViewModel для формы, содержащий поле Boolean:
    
    public class CheckboxViewModel
    {
    [Display(Name="Test checkbox")]
    public bool TestCheckbox { get; set; }
    }
    
  • Создано действие контроллера, которое просто подготавливает форму ViewModel и визуализирует:
    
    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" />
    }
    
  • Создано действие веб-API, которое проверяет, является ли modelstate действительным, и возвращает код состояния 200, иначе 400:
    
    public HttpResponseMessage Post(CheckboxViewModel model)
    {
        if (!ModelState.IsValid)
            return new HttpResponseMessage(HttpStatusCode.BadRequest);
        return new HttpResponseMessage(HttpStatusCode.OK);
    }
    

Я сделал несколько поисковых запросов, и я знаю, что редактор для флажка предоставляет дополнительное скрытое поле, но, похоже, он подходит и необходим для привязки модели. Поэтому, когда я сниму флажок и отправлю форму, все работает нормально, сервер отвечает со статусом 200, благодаря скрытому полю, я полагаю. Однако, когда я делаю checkbox проверен и отправил форму, сервер отвечает со статусом 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: true и TestCheckbox:false, поэтому я думаю, что это может быть какое-то действие, затрагивающее связующее вещество и вызывающее исключение. По-прежнему нет параметров, как обходиться с этим.

Ответ 1

Я столкнулся с той же проблемой, отправив форму в веб-API с JavaScript. Вот основное решение, которое вы можете использовать для решения этой проблемы. Я знаю, что это просто упрощенный или даже уродливый - и не очень практичный, если у вас много флажков. Однако идея проста и может быть легко расширена для удовлетворения ваших требований.

Добавьте это перед отправкой формы (используя 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/

Ответ 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 задает значение скрытого значения chechbox истинным результатам при установке свойства модели true для значения, ожидаемого иначе false по умолчанию.

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