2015-07-22 2 views
1

Я очень новичок в asp.net mvc, поэтому причиной моего отказа может быть что-то основное, но я не могу найти его после почти дня работы.Неспособность передать данные из представления в действие по Html.BeginForm()

То, что я пытаюсь сделать, это получить отредактированную модель из представления индекса и передать ее второму действию, которое не имеет вида и возвращает возврат RedirectToAction("Index") в связанном контроллере. В OrdersItemsController мое действие как следующее:

[HttpPost] 
[ValidateAntiForgeryToken] 
public ActionResult MarkedShipped(IEnumerable<orders_items> orderItems) 
{ 
    if (ModelState.IsValid) 
    { 
     foreach (var item in orderItems) 
     { 
      unitOfWork.GenericRepository<orders_items>().Update(item); 
     } 
    } 
    return RedirectToAction("Index"); 
} 

И в Index.cshtml, который находится в папке OrdersItems в соображениях, что я сделал это следующим образом:

@model IEnumerable<Project.DataAccess.orders_items> 
@{ 
    ViewBag.Title = "Index"; 
} 

<h2>Index</h2> 

@using (Html.BeginForm("MarkedShipped", "OrdersItems", new { orderItems = Model })) 
{ 

    @Html.AntiForgeryToken() 
    @Html.ValidationSummary(true) 

    <table class="table"> 
     <tr> 
      <th> 
       @Html.DisplayNameFor(model => model.quantity) 
      </th> 
      <th> 
       @Html.DisplayNameFor(model => model.itemprice) 
      </th> 
      <th> 
       @Html.DisplayNameFor(model => model.trackingnumber) 
      </th> 
     </tr> 

     @foreach (var item in Model) 
     { 
      <tr> 
       <td> 
        @Html.DisplayFor(modelItem => item.quantity) 
       </td> 
       <td> 
        @Html.DisplayFor(modelItem => item.itemprice) 
       </td> 
       <td> 
        @Html.EditorFor(modelItem => item.trackingnumber) 
       </td> 
       <td> 
        @Html.ActionLink("Edit", "Edit", new { id = item.itemid }) 
       </td> 
      </tr> 

     } 
    </table> 
    <div class="form-group"> 
     <div class="col-md-offset-2 col-md-10"> 
      <input type="submit" value="MarkShipped" class="btn btn-default" /> 
     </div> 
    </div> 
} 

Моя проблема, я я не могу получить модель из представления с параметром orderItems, я не уверен, что это правильный «синтаксис» для того, что я пытаюсь выполнить; но то, что я получаю для orderItems, когда вызывается действие, является списком orders_items с Count = 0, а не нулевым значением.

Я также проверил, есть ли исключения на уровне приложения, но не получил никакого исключения из Application_Error в Global.asax

Я застрял в течение дня теперь так если кто-нибудь может указать мне направление, как пройти Model (или «отредактированные данные») к действию для меня, чтобы обновить db, я был бы очень благодарен. Благодарю.

+1

Поместите форму FormMethod.Post в параметры BeginForm. – Neel

+1

Вы не можете использовать цикл 'foreach' - он генерирует повторяющиеся атрибуты' name' без индексаторов, необходимых для привязки к коллекции и дублировать атрибуты id, которые являются недопустимыми html. Вам нужно использовать цикл 'for' (или пользовательский' EditorTemplate' для типа вашей модели). Ваша модель должна быть 'IList ', а затем' @for (int i = 0; i m [i] .trackingnumber) ...} ' –

+1

И вы не можете добавить свою модель в качестве параметра маршрута - это сборник, который означает, что привязка не сработает (посмотрите на HTML-код, который генерирует для понимания). И в любом случае, какой смысл добавлять исходную модель в качестве параметра маршрута в любом случае (вы уже знаете, что это такое на сервере). –

ответ

1

Во-первых, вы не можете добавить модель, которая представляет собой коллекцию (или модель, которая содержит свойство, представляющее собой сложный объект или коллекцию) для параметров маршрута форм. Внутренне помощник вызывает метод .ToString() и если вы осмотрите HTML сгенерированное для тега формы вы увидите что-то вроде

<form action=OrdersItems/MarkedShipped?orderItems=System.Collection.Generic....... 

и связывания потерпит неудачу, так как вы коллекция не может быть привязана к строке. Даже если бы это сработало, это было бы совершенно бессмысленно, потому что оно просто возвращало исходные значения модели.

Далее вы не можете использовать цикл foreach для создания элементов управления формой. Опять же, если вы проверите html свою генерацию, вы увидите, что метод EditorFor() генерирует входы с дублирующимися атрибутами id (недопустимый html) и дублирует атрибуты name, которые не имеют необходимых индексаторов для привязки к коллекции при публикации.Вы должны использовать либо for петлю обычая EditorTemplate для TYPEOF orders_items

Использование for цикла означает, что ваша модель должна реализовать IList<T> и вид должен быть

@model IList<Hochanda.CraftsHobbiesAndArts.DataAccess.orders_items> 
@using (Html.BeginForm()) // only necessary to add the controller and action if they differ from the GET method 
{ 
    .... 
    @for(int i = 0; i < Model.Count; i++) 
    { 
    @Html.DisplayFor(m => m[i].quantity) 
    .... 
    @Html.EditorFor(m => m[i].trackingnumber) 
    } 
    .... 
} 

Использование EditorTemplate, создать частичный в /Views/Shared/EditorTemplates/orders_items.cshtml (обратите внимание на имя файла должно совпадать с именем класса)

@model Hochanda.CraftsHobbiesAndArts.DataAccess.orders_items 
<tr> 
    <td>@Html.DisplayFor(m => m.quantity)</td> 
    .... 
    <td>@Html.EditorFor(m => m.trackingnumber)</td> 
    .... 
</tr> 

, а затем в главном окне (вы с использование IEnumerable<T>)

@model IEnumerable<Hochanda.CraftsHobbiesAndArts.DataAccess.orders_items> 
@using (Html.BeginForm()) 
{ 
    <table class="table"> 
    <thead> 
     .... 
    <thead> 
    <tbody> 
     @Html.EditorFor(m => m) 
    </tbody> 
    </table> 
    .... 
} 

Метод EditorFor() принимает IEnumerable<T> и будет генерировать одну строку для каждого элемента в вас коллекции на основе HTML в EditorTemplate

В обоих случаях вы проверить HTML вы теперь см. правильные атрибуты имени, необходимые для привязки модели, когда вы отправляете

<input type="text" name="[0].trackingnumber" ... /> 
<input type="text" name="[1].trackingnumber" ... /> 
<input type="text" name="[3].trackingnumber" ... /> 
+0

Большое спасибо за этот ответ, я реализовал, как вы объяснили, и работает отлично, как и ожидалось. Вы очень помогли. Благодаря! – biseibutsu

1

Попробуйте вместо foreach здесь.

@for (int i = 0; i < Model.Count; i++) 
     { 
      <tr> 
       <td> 
        @Html.DisplayFor(modelItem => item.quantity) 
       </td> 
       <td> 
        @Html.DisplayFor(modelItem => item.itemprice) 
       </td> 
       <td> 
        @Html.EditorFor(modelItem => item.trackingnumber) 
       </td> 
       <td> 
        @Html.ActionLink("Edit", "Edit", new { id = item.itemid }) 
       </td> 
      </tr> 
     } 

Проверьте это: - http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx/

+0

Я реализовал это, я удалил foreach и добавил цикл for, но это не помогает мне передавать данные обратно контроллеру. – biseibutsu

0

Вы можете сделать следующее

for (int i = 0; i < @ViewBag.Persons; i++) 
    { 

    <li> 
     <table> 

      <tr> 
       <td> 
        @Html.LabelFor(m => m.Fullname,new { @id = "FullnameLabel" + @i }) 
       </td> 
       <td> 
        @Html.TextBoxFor(m => m.Fullname, new { @id = "Fullname" + @i }) 
       </td> 

      </tr> 

Таким образом, каждый HTML элемент получает свой уникальный идентификатор и его можно получить информацию от них по отдельности , Вы можете использовать for или Foreach. Просто убедитесь, что ваш итератор бритвы функционирует. Вы можете просмотреть идентификаторы элементов в источнике, чтобы узнать, работает ли он.

+0

. Вы НЕ МОЖЕТЕ использовать цикл foreach, а html-помощники будут генерировать уникальный 'id' атрибуты внутри цикла 'for', поэтому переопределение его бессмысленно. В любом случае атрибуты 'id' не имеют к этому никакого отношения - его значения атрибутов' name' и 'value', которые отправляются обратно контроллеру –

+0

Im генерирует html динамически с помощью бритвы. Если вы не заставляете задавать идентификаторы (например, я это сделал), вы получаете только значения, введенные в первом блоке, когда смотрите на свою модель в контроллере. – Anubis77

+0

Вам нужно изучить некоторые основы MVC. Правильное использование выполняется в соответствии с моим первым комментарием к вопросу - i.e '@ Html.EditorFor (m => m [i] .trackingnumber). Вы неправильно кодируете код и не работаете. –

Смежные вопросы