Frage

I have an app that calls a web service to display import records based upon criteria entered by the user.

Each "import" can have 0 to many PurchaseOrder, 0 to many Containers, 0 to many Products, 0 to many Invoices.

the View (displaying the inquiry) works fine, bur when I click on a submit button the controller is not getting the "import" info thru the viewmodel. I can gain access to these controls via the "formCollection".

What am I missing ????

Here is my code...

Model...

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_2_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; }
    }  
}

Here is my view (partial)

<% 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>

Here is my contoller...

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);
        }

I have not posted the fullness of the View / Controller....

It works to render the view....

When i submit the view / form the controller only has access to the items in the main part of the viewmodel (nothing in the "lists" comes thru).

I can gain access to these other controls via the "formcollection".

I am wondering why there are null in the viewmodel.

War es hilfreich?

Lösung 3

I was attempting to pass the viewmodel in a RedirectToAction..

Have discovered this doesn't work that way.

Thanks everyone for your assistance.

Andere Tipps

Your problem is that you are not naming your fields in a way that MVC model binder can understand that they're part of a nested class. For each row, you simply have a field with the same name. That doesn't work.

This is one of the reasons you shouldn't use the non-type safe versions of the helper classes, because the type safe versions will automatically generate the correct names. You should also take advantage of the EditorTemplates, because they do the right thing for collections, and automatically iterate over the collection.

Read http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-1-introduction.html

If you must do it the way you're doing it, then you need to include array syntax in the name. Use a for statement rather than a foreach, and use the counter to count the row number. Do something like this:

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

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

    ....
<% } %>

Read more here: http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx

I think what you missing is a few @HiddenFor clauses for values you don't get in the model. If I understood you correctly you getting some of them but not all of them. So those you aren't getting, define @HiddenFor for them and see what happens.

Update

This is what stack overflow says about nested view models:

Nested ViewModel Classes in asp.net MVC

Update 2

Look into here, seem very similar to your problem:

ASP.net MVC2. Populated model is not getting back to the controller

Hope this helps

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top