Контроллер MVC2 не получает все данные из представления при отправке

У меня есть приложение, которое вызывает веб-службу для отображения записей импорта на основе критериев, введенных пользователем.

Каждый «импорт» может иметь от 0 до многих PurchaseOrder, от 0 до многих контейнеров, от 0 до многих продуктов, от 0 до многих счетов-фактур.

представление (отображающее запрос) работает нормально, но когда я нажимаю кнопку отправки, контроллер не получает информацию об «импорте» через модель представления. Я могу получить доступ к этим элементам управления через «formCollection».

Что мне не хватает????

Вот мой код...

Модель...

namespace LemansCorpIntranet.Models
{    
    public class ImportWebViewModel
    {
        public string button { get; set; }
        public string status_filter { get; set; }
        public string import_id_filter { get; set; }
        public DateTime date_filter { get; set; }
        public string vendor_filter { get; set; }
        public string port_filter { get; set; }
        public string whse_filter { get; set; }
        public Boolean not_released_filter { get; set; }
        public int release_gap { get; set; }
        public List<import_row> import_rows;   /// this is the piece that is not coming
                                               // thru on the POST
    }

    public class import_row
    {
        public string update_switch { get; set; }
        public string id { get; set; }
        public IEnumerable<SelectListItem> ship_via { get; set; }
        public string broker_number { get; set; }
        public string voyage { get; set; }
        public string vessel { get; set; }
        public decimal shipment_value { get; set; }
        public int cartons { get; set; }
        public decimal weight { get; set; }
        public decimal volume { get; set; }
        public string clearance_port { get; set; }
        public string warehouses_in_shipment { get; set; }
        public string payment_type { get; set; }
        public string insurance { get; set; }
        public DateTime ship_date { get; set; }
        public DateTime close_date { get; set; }
        public DateTime customs_date { get; set; }
        public string customs_entry { get; set; }
        public DateTime pl
<% using (Html.BeginForm("ImportLog", "ImportWeb")) %>
    <%  { %>
            <table style="position:fixed">
.
.
.
<% if (Model.import_rows != null) %>
<% { %>
<%   var row_number = 0; %>
     <table id="import_web_detail">
<%   foreach (var row in Model.import_rows) %>
<%   { %>
<%     if (row.id != "          ")%>
<%     { %>
<%       row_number++; %>
         <tr style="vertical-align:top">
           <td style="width:.5em" />
           <td align="center">
             <table>
               <tr>
                 <td colspan="4"></td>
                 <td><%=Html.CheckBox("update_switch", row.update_switch)%></td>
                 <td colspan="4"></td>
               </tr>
             </table>
           </td>
           <td />
           <td>
             <table>
               <tr>
                 <td><%=Html.TextBox("import_id", row.id)%></td>
               </tr>
             </table>
           </td>
whse_date { get; set; } public DateTime estimated_arrival_date { get; set; } public DateTime wire_transfer_request_done_date { get; set; } public DateTime approved_broker_bill_date { get; set; } public DateTime product_released_date { get; set; } public List<Invoice> Invoices; public List<PurchaseOrder> PurchasOrders; public List<Product> Products; public List<Container> Containers; } public class Invoice { public string invoice_number { get; set; } } public class PurchaseOrder { public string id { get; set; } public string whse { get; set; } public string vendor_code { get; set; } public string vendor_name { get; set; } } public class Product { public int line_number { get; set; } public string description { get; set; } } public class Container { public int line_number { get; set; } public int size { get; set; } public string id { get; set; } public string seal { get; set; } public DateTime received_date { get; set; } public int cartons { get; set; } } }

Вот мое мнение (частично)

<% using (Html.BeginForm("ImportLog", "ImportWeb")) %>
    <%  { %>
            <table style="position:fixed">
.
.
.
<% if (Model.import_rows != null) %>
<% { %>
<%   var row_number = 0; %>
     <table id="import_web_detail">
<%   foreach (var row in Model.import_rows) %>
<%   { %>
<%     if (row.id != "          ")%>
<%     { %>
<%       row_number++; %>
         <tr style="vertical-align:top">
           <td style="width:.5em" />
           <td align="center">
             <table>
               <tr>
                 <td colspan="4"></td>
                 <td><%=Html.CheckBox("update_switch", row.update_switch)%></td>
                 <td colspan="4"></td>
               </tr>
             </table>
           </td>
           <td />
           <td>
             <table>
               <tr>
                 <td><%=Html.TextBox("import_id", row.id)%></td>
               </tr>
             </table>
           </td>

Вот мой контроллер...

namespace LemansCorpIntranet.Controllers
{
    public class ImportWebController : Controller
    {
        eptest_importweb_svc.Service importweb_svc = new eptest_importweb_svc.Service();

        //
        // Import Web Request

        public ActionResult ImportLog(ImportWebViewModel import_request)
        {// import_request.import_rows is null. should be loaded with view detail
            switch (import_request.button)
            {
                case "Next":
                case "Previous":
                    return RedirectToAction("ImportPage", import_request);
                case "Update":
                    return RedirectToAction("ImportUpdate");
                case "Importlog":
                    return RedirectToAction("ImportReport");
                default:
                    break;
            }
            // ----------------------------------
            // fall thru for initial page display
            // ----------------------------------


            //     load "date filter" with default. 300 days in the past.
            //     ------------------------------------------------------
            import_request.date_filter = new DateTime(DateTime.Now.Year - 1,  
                                  DateTime.Now.Month, DateTime.Now.Day).AddDays(65);

            return View("ImportLog", import_request);
        }

Я не выложил полноту View/Controller....

Он работает, чтобы отобразить вид....

Когда я отправляю представление/форму, контроллер имеет доступ только к элементам в основной части модели представления (ничего в «списках» не происходит).

Я могу получить доступ к этим другим элементам управления через «коллекцию форм».

Мне интересно, почему в модели представления есть ноль.


person hyperstaff    schedule 21.09.2012    source источник
comment
Это много кода. Можете ли вы сузить список до тех элементов, которые не приходят по почте?   -  person Erik Funkenbusch    schedule 21.09.2012
comment
Я обновил выше, чтобы сократить код....   -  person hyperstaff    schedule 21.09.2012
comment
Вероятно, вам понадобится скрытый элемент для каждого свойства каждого из «вложенных» классов.   -  person Forty-Two    schedule 24.09.2012


Ответы (3)


Ваша проблема в том, что вы не называете свои поля таким образом, чтобы связыватель модели MVC мог понять, что они являются частью вложенного класса. Для каждой строки у вас просто есть поле с тем же именем. Это не работает.

Это одна из причин, по которой вам не следует использовать небезопасные версии вспомогательных классов, потому что безопасные версии автоматически генерируют правильные имена. Вы также должны воспользоваться преимуществами EditorTemplates, потому что они подходят для коллекций и автоматически перебирают коллекцию.

Прочитайте http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-1-introduction.html

Если вы должны сделать это так, как вы это делаете, вам нужно включить синтаксис массива в имя. Используйте оператор for, а не foreach, и используйте счетчик для подсчета номера строки. Сделайте что-то вроде этого:

<% for(int row = 0; row < Model.import_rows.Count; row++) { %>
    ....

    <td><%=Html.CheckBoxFor(x => Model.import_rows[row].update_switch)%></td>

    ....
<% } %>

Подробнее читайте здесь: http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx

person Erik Funkenbusch    schedule 24.09.2012

Я думаю, что вам не хватает нескольких предложений @HiddenFor для значений, которые вы не получаете в модели. Если я правильно вас понял, вы получаете некоторые из них, но не все из них. Так что те, кого вы не получаете, определите для них @HiddenFor и посмотрите, что произойдет.

Обновить

Вот что говорит переполнение стека о вложенных моделях представлений:

Вложенные классы ViewModel в asp.net MVC

Обновление 2

Посмотрите здесь, похоже, очень похоже на вашу проблему:

ASP.net MVC2. Заполненная модель не возвращается к контроллеру

Надеюсь это поможет

person Display Name    schedule 21.09.2012
comment
проблема не в получении данных в модели и, следовательно, в отображении представления. Рендеринг представления работает нормально, когда представление публикуется, некоторая часть модели представления не попадает в контроллер. Вложенные классы - это проблема... - person hyperstaff; 24.09.2012

Я пытался передать модель представления в RedirectToAction.

Обнаружил, что это так не работает.

Спасибо всем за вашу помощь.

person hyperstaff    schedule 25.09.2012