Сегодня мне вдруг стало любопытно, как происходит байндинг булевых полей в MVC.
Причину любопытства можно пояснить на примере:
Допустим, у нас есть модель:
public class TestModel {
public string Name {get;set;}
public bool IsDeleted {get;set;}
}
И есть две хтмл-формы для редактирования этой модели, в первой из которых присутствует флаг IsDeleted, а во второй — нет:
Форма 1:
@using (Html.BeginForm) {
@Html.TextboxFor(x => x.Name)
@Html.CheckboxFor(x => x.IsDeleted)
<input type="submit" value="OK" />
}
Форма 2:
@using (Html.BeginForm) {
@Html.TextboxFor(x => x.Name)
<input type="submit" value="OK" />
}
При этом серверный обработчик этой формы выглядит вполне типично:
public ActionResult UpdateModel(int id) {
var model = Db.Load<TestModel>(id);
TryUpdateModel(model);
return RedirectToAction();
}
Предположим, что в базе у TestModel IsDeleted == true. Что произойдет, если
- мы отсабмитим Форму1 со снятым флагом?
- мы отсабмитим Форму2, в которой флага IsDeleted просто нет?
Как и ожидалось, в обоих случаях MVC отработал отлично, и в случае 1 в базе у сущности TestModel поле IsDeleted стало false, а в случае 2 — осталась в true.
В чем же причина любопытства? Мне было любопытно, как же именно это работает.
В «классическом html» чекбоксы обычно представлены в виде <input name=’IsDeleted’ type=’checkbox’ />. А при сабмите формы на сервер это отправляется в виде:
- http://localhost/?name=zcx&IsDeleted=on — если флажок проставлен
- http://localhost/?name=zcx — если флажок не стоит
Как видно, в «классическом случае» ситуация отсутствия чекбокса в форме как такового и ситуация, когда он есть, но «галочка не стоит» абсолютно одинаковы, и выполнить корректный байндинг не представляется возможным.
Именно поэтому мне было интересно заглянуть «под капот» и узнать, как же это реализовано в mvc3.
Решение оказалось простым: на каждое булево поле mvc генерит такой html:
<input type="checkbox" name="IsDeleted" value="true" /><input type="hidden" name="IsDeleted" value="false" />
Вот и весь секрет :)
Возможно, это вполне стандартный прием у веб-программистов, но я о нём почему-то не знал, потому восполнить пробел было очень любопытно, и, уверен, этот приём мне еще не раз пригодится на практике.