ASP.NET MVC 2: Необязательные URL-параметры
Если у вас объект модели имеет свойство 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> <% } %> <p > </p>
Метод действия выглядит так:
[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