Если у вас объект модели имеет свойство Id, то вы столкнетесь с проблемой, когда состояние модели будет невалидным при связывании с этой моделью, даже когда у вас отсутствует поле "Id" в форме.
Следующая ситуация более понятно объяснит к чему я клоню. Предпологается, что у вас есть модель с двумя свойствами.
public class Product {
public int Id { get; set; }
public string Name { get; set; }
}
Добавляете представление для создания нового Product. Вы конечно же не хотите, чтобы пользователь задавал Id.
<% using (Html.BeginForm()) {%>
<fieldset>
<legend>Fields</legend>
<div class="editor-label">
<%= Html.LabelFor(model => model.Name) %>
</div>
<div class="editor-field">
<%= Html.TextBoxFor(model => model.Name) %>
<%= Html.ValidationMessageFor(model => model.Name) %>
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
<% } %>
Метод действия выглядит так:
[HttpPost]
public ActionResult Index(Product p)
{
if (!ModelState.IsValid) {
throw new InvalidOperationException("Modelstate not valid");
}
return View();
}
Вы обнаружите, что состояние модели невалидно. В чем же причина? Проблема в том, что свойство Id, объекта Product устанавливается, как пустая строка. Почему же так происходит, когда поле Id не присутствует в форме? Ответ, друзья мои, прост - всему виной маршрутизация.
Если открыть свеже-созданный проект ASP.NET MVC 1.0, то можно увидеть объявление маршрутизатора по умолчанию
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = "" }
);
Напомню, в проекте имеется маршрутизатор с тремя URL-параметрами (controller, action, id), каждые имеет значение по умолчанию ("home", "index", "").
Соответственно, если вы будете отсылать данные формы по адресу /Home/Index, без указания "ID" в URL, то маршрутизатор подставит пустую строку для ключа "id". Теперь нам ясно, что используются значения маршрутизатора для связки с параметрами метода действия.
В итоге, случилась "накладка", когда свойство вашего объекта модели "Id", имееет точно такое же имя, как и у параметра маршрутизатора, а модель привязки пытается присвоить значению свойства Id пустую строку. Но Id является целым числом не равное null, соответственно у нас возникает ошибка приведения типов.
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
И немного изменив настройки роутера, мы изменяем логику - если не передается ID в URL, то не будет производиться подстановка значения по умолчанию, что не приведет к заданию значения свойства "Id", до тех пор, пока мы не добавим поле "Id" на форму.
Начиная с ASP.NET MVC 2 RTM версии, стандартный шаблон проекта будет с измененным видом роутера.
Источник - Phil Haack
1