none
Modelo ViewModel no retorna todos los datos. RRS feed

  • Pregunta

  • Hola:

    Tengo un viewmodel para un maestro detalle el cual está compuesto por lo siguiente:

    public class ClienteEditViewModel
        {
            public ClienteEditViewModel()
            {
                cliente = new Cliente();
                cliente.CCCClientes = new List<CCCCliente>();
                cccClienteEdit = new CCCCliente();
            }
            
    
            public Cliente cliente { get; set; }
            public CCCCliente cccClienteEdit { get; set; }
    
        }


    En la vista principal paso los datos del viewmodel y el criente se edita en este sin problemas, pero las lista de datos CCCClientes los paso a través de una vista parcial y cuando retorno los datos  los datos CCCCliente no los retorna.

    El archivo de edición principal es:

    @model Entities.ClienteEditViewModel
    
    @{
    
        ViewBag.Title = "Editar";
    }
    <hr />
    <h2>Editar Cliente:  @Html.DisplayFor(model => model.cliente.Nombre)</h2>
    
    
    @using (Html.BeginForm())
    {
        @Html.AntiForgeryToken()
    
    <div class="form-horizontal">
    
    
        @Html.ValidationSummary(false, "", new { @class = "text-danger" })
        @Html.HiddenFor(model => model.cliente.EmpresaId)
        @Html.HiddenFor(model => model.cliente.ClienteId)
        @Html.HiddenFor(model => model.cliente.CCCClientes)
    
        
    
    
        @Html.EditorFor(m => m.cliente, "EditorCliente")
    </div>
    
        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
    
                @Html.ActionLink("Back to List", "Index", null, new { @class = "btn btn-primary" })
                <input type="submit" value="Guardar" name="Accion" class="btn btn-success" />
            </div>
        </div>
    
    
        @* Inicio Tabs *@
        <div class="">
            <ul class="nav nav-tabs" id="myTab" role="tablist">
                <li class="nav-item">
                    <a class="nav-link active" id="ccc-tab" data-toggle="tab" href="#ccc" role="tab" aria-controls="ccc" aria-selected="true">CCC</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" id="profile-tab" data-toggle="tab" href="#profile" role="tab" aria-controls="profile" aria-selected="false">Profile</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" id="contact-tab" data-toggle="tab" href="#contact" role="tab" aria-controls="contact" aria-selected="false">Contact</a>
                </li>
            </ul>
            <div class="tab-content " id="myTabContent">
                <div class="tab-pane fade show active p-2 bg-light mb-3" id="ccc" role="tabpanel" aria-labelledby="ccc-tab">
                    @Html.EditorFor(m => m.cccClienteEdit, "EditorCCCMin")
                    @if (Model.cliente.CCCClientes.Count > 0)
                    {
                        @Html.EditorFor(m => m.cliente.CCCClientes, "ListaCCC")
                    }
    
                </div>
                <div class="tab-pane fade p-2 bg-light mb-3" id="profile" role="tabpanel" aria-labelledby="profile-tab">...</div>
                <div class="tab-pane fade p-2 bg-light mb-3" id="contact" role="tabpanel" aria-labelledby="contact-tab">...</div>
            </div>
        </div>
        @*Fin Tabs*@
    
    
    }
    
    <div>
    
    </div>
    
    @section Scripts {
        @Scripts.Render("~/bundles/jqueryval")
    }
    

    Y la vista parcial que está en la carpeta de EditorTemplates es:

    @model IEnumerable<Entities.CCCCliente>
    
    <table id="miTabla" class="display compact " style="width:100%">
        <thead class="text-primary">
            <tr>
                <td>@Html.DisplayNameFor(model => model.CCCClienteId)</td>
                <td>@Html.DisplayNameFor(model => model.Banco.Nombre)</td>
                <td>@Html.DisplayNameFor(model => model.iban)</td>
                <td>@Html.DisplayNameFor(model => model.BIC)</td>
                <td>@Html.DisplayNameFor(model => model.RefMandato)</td>
                <td>@Html.DisplayNameFor(model => model.FechaMandato)</td>
                <td></td>
            </tr>
        </thead>
    
        <tbody>
    
            @foreach (var item in Model)
            {
                @Html.HiddenFor(modelItem => item.CCCClienteId)
                @Html.HiddenFor(modelItem => item.BancoId)
                @Html.HiddenFor(modelItem => item.iban)
                @Html.HiddenFor(modelItem => item.BIC)
                @Html.HiddenFor(modelItem => item.RefMandato)
                @Html.HiddenFor(modelItem => item.FechaMandato)
                @Html.HiddenFor(modelItem => item.ClienteId)
                <tr>
                    <td>@Html.DisplayFor(modelItem => item.CCCClienteId)</td>
                    <td>@Html.DisplayFor(modelItem => item.Banco.Nombre)</td>
                    <td>@Html.DisplayFor(modelItem => item.iban)</td>
                    <td>@Html.DisplayFor(modelItem => item.BIC)</td>
                    <td>@Html.DisplayFor(modelItem => item.RefMandato)</td>
                    <td>@Html.DisplayFor(modelItem => item.FechaMandato)</td>
    
    
                    <td style="min-width: 95px">
                        <div class="dropdown" position="relative">
                            <button class="btn btn-primary dropdown-toggle" type="button" id="Acciones" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" data-target="Accion">
                                Acciones
                            </button>
                            <div id="Accion" class="dropdown-menu pruebas " aria-labelledby="Acciones">
                                @Html.ActionLink("Editar", "Edit", new { id = item.ClienteId }, new { @class = "dropdown-item" })
                                @Html.ActionLink("Detalles", "Details", new { id = item.ClienteId }, new { @class = "dropdown-item" })
                                <div class="dropdown-divider"></div>
                                @Html.ActionLink("Eliminar", "Delete", new { id = item.ClienteId }, new { @class = "dropdown-item" })
                            </div>
                        </div>
                    </td>
    
                </tr>
    
            }
        </tbody>
        <tfoot>
            <tr class="text-primary">
                <td>@Html.DisplayNameFor(model => model.CCCClienteId)</td>
                <td>@Html.DisplayNameFor(model => model.Banco.Nombre)</td>
                <td>@Html.DisplayNameFor(model => model.iban)</td>
                <td>@Html.DisplayNameFor(model => model.BIC)</td>
                <td>@Html.DisplayNameFor(model => model.RefMandato)</td>
                <td>@Html.DisplayNameFor(model => model.FechaMandato)</td>
                <td></td>
            </tr>
        </tfoot>
    
    </table>

    ¿Como puedo hacer para que me devuelva los datos de la vista parcial (CCCCliente) al controlador?

    Un Saludo.

    domingo, 16 de diciembre de 2018 0:09

Respuestas

  • porque no evaluas aplamar un poco los datos usando

    public class ClienteEditViewModel { public ClienteEditViewModel() { cliente = new Cliente(); CCCClientes = new List<CCCCliente>(); cccClienteEdit = new CCCCliente(); } public Cliente cliente { get; set; }

     public List<CCCCliente> cccClientes { get; set; } public CCCCliente cccClienteEdit { get; set; } }

    a ver si asi lo bindea

    El tema es que hay que analizar como llegan los datos en el post para realizar un binding por defecto

    Sino el otro camino es extender el binding y crear un custom

     Model Binding And Custom Model Binding in ASP.NET MVC

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    • Marcado como respuesta elturle lunes, 17 de diciembre de 2018 10:11
    domingo, 16 de diciembre de 2018 21:23

Todas las respuestas

  • hola

    el problema es como estas asignando el modelo a los @Html.displayFor()

    ASP.NET MVC 5 View Model Collection Binding

    analiza como usa el for para poder tenr el index del modelo

    @for (var i = 0; i < Model.CalendarEntries.Count; i++) 
        {
            <div class="calendar-entry">
                Subject: @Html.TextBoxFor(x => x.CalendarEntries[i].Subject)<br/>
                Date: @Html.TextBoxFor(x => x.CalendarEntries[i].Date)<br/>
                Location: @Html.TextBoxFor(x => x.CalendarEntries[i].Location)<br/>
                Required: @Html.CheckBoxFor(x => x.CalendarEntries[i].Required)<br/>
            </div>
        }

    no aplic usar un foreach en este caso porque necesitas que el nombre del controles se genere como array

    inspecciona cuando realizas el submit como se envian los datos en el body del post y te daras cuenta

    Model Binding to List of Objects in ASP.NET MVC

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina


    domingo, 16 de diciembre de 2018 15:36
  • hola

    >>Lo que me indicas es cuando todo está en la misma vista, pero yo tengo, digamos según tu ejemplo, en una vista parcial

    quizas no puedas hacer vista parcial en este caso

    >>he probado lo siguiente y no funciona da error ("No se puede aplicar la indización con [] a una expresión de tipos IEnumerable<CalendarEntries>":

    intenta definiendo List<CalendarEntries> para el modelo de la vista, pero envia un List<> como dato para esa view cuando se renderice

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    domingo, 16 de diciembre de 2018 18:38
  • Hola:

    Lo de IEnumerable lo he arreglado como me has dicho.

    En la vista, he quitado la vista parcial y la he metido dentro de ecit.cshtml, pero sigue sin devolverme el listado de CCCCliente.

    @model Entities.ClienteEditViewModel
    
    @{
    
        ViewBag.Title = "Editar";
    }
    <hr />
    <h2>Editar Cliente:  @Html.DisplayFor(model => model.cliente.Nombre)</h2>
    
    
    @using (Html.BeginForm())
    {
        @Html.AntiForgeryToken()
    
    <div class="form-horizontal">
    
    
        @Html.ValidationSummary(false, "", new { @class = "text-danger" })
        @Html.HiddenFor(model => model.cliente.EmpresaId)
        @Html.HiddenFor(model => model.cliente.ClienteId)
        @Html.HiddenFor(model => model.cliente.CCCClientes)
    
        
    
    
        @Html.EditorFor(m => m.cliente, "EditorCliente")
    </div>
    
        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
    
                @Html.ActionLink("Back to List", "Index", null, new { @class = "btn btn-primary" })
                <input type="submit" value="Guardar" name="Accion" class="btn btn-success" />
            </div>
        </div>
    
    
        @* Inicio Tabs *@
        <div class="">
            <ul class="nav nav-tabs" id="myTab" role="tablist">
                <li class="nav-item">
                    <a class="nav-link active" id="ccc-tab" data-toggle="tab" href="#ccc" role="tab" aria-controls="ccc" aria-selected="true">CCC</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" id="profile-tab" data-toggle="tab" href="#profile" role="tab" aria-controls="profile" aria-selected="false">Profile</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" id="contact-tab" data-toggle="tab" href="#contact" role="tab" aria-controls="contact" aria-selected="false">Contact</a>
                </li>
            </ul>
            <div class="tab-content " id="myTabContent">
                <div class="tab-pane fade show active p-2 bg-light mb-3" id="ccc" role="tabpanel" aria-labelledby="ccc-tab">
                    @Html.EditorFor(m => m.cccClienteEdit, "EditorCCCMin")
                    @if (Model.cliente.CCCClientes.Count > 0)
                    {
    
                    <table id="miTabla" class="display compact " style="width:100%">
                        <thead class="text-primary">
                            <tr>
                                <td>@Html.DisplayNameFor(model => model.cccClienteEdit.CCCClienteId)</td>
                                <td>@Html.DisplayNameFor(model => model.cccClienteEdit.Banco.Nombre)</td>
                                <td>@Html.DisplayNameFor(model => model.cccClienteEdit.iban)</td>
                                <td>@Html.DisplayNameFor(model => model.cccClienteEdit.BIC)</td>
                                <td>@Html.DisplayNameFor(model => model.cccClienteEdit.RefMandato)</td>
                                <td>@Html.DisplayNameFor(model => model.cccClienteEdit.FechaMandato)</td>
                                <td></td>
                            </tr>
                        </thead>
    
                        <tbody>
    
                            @for (var i = 0; i < Model.cliente.CCCClientes.Count; i++)
                            {
                                @Html.HiddenFor(m => m.cliente.CCCClientes[i].CCCClienteId)
                                @Html.HiddenFor(m => m.cliente.CCCClientes[i].BancoId)
                                @Html.HiddenFor(m => m.cliente.CCCClientes[i].BancoId)
                                @Html.HiddenFor(m => m.cliente.CCCClientes[i].iban)
                                @Html.HiddenFor(m => m.cliente.CCCClientes[i].BIC)
                                @Html.HiddenFor(m => m.cliente.CCCClientes[i].RefMandato)
                                @Html.HiddenFor(m => m.cliente.CCCClientes[i].FechaMandato)
                                @Html.HiddenFor(m => m.cliente.CCCClientes[i].ClienteId)
                                <tr>
                                    <td>@Html.DisplayFor(m => m.cliente.CCCClientes[i].CCCClienteId)</td>
                                    <td>@Html.DisplayFor(m => m.cliente.CCCClientes[i].Banco.Nombre)</td>
                                    <td>@Html.DisplayFor(m => m.cliente.CCCClientes[i].iban)</td>
                                    <td>@Html.DisplayFor(m => m.cliente.CCCClientes[i].BIC)</td>
                                    <td>@Html.DisplayFor(m => m.cliente.CCCClientes[i].RefMandato)</td>
                                    <td>@Html.DisplayFor(m => m.cliente.CCCClientes[i].FechaMandato)</td>
    
    
                                    <td style="min-width: 95px">
                                        <div class="dropdown" position="relative">
                                            <button class="btn btn-primary dropdown-toggle" type="button" id="Acciones" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" data-target="Accion">
                                                Acciones
                                            </button>
                                            <div id="Accion" class="dropdown-menu pruebas " aria-labelledby="Acciones">
                                                @Html.ActionLink("Editar", "Edit", new { }, new { @class = "dropdown-item" })
                                                @Html.ActionLink("Detalles", "Details", new { }, new { @class = "dropdown-item" })
                                                <div class="dropdown-divider"></div>
                                                @Html.ActionLink("Eliminar", "Delete", new { }, new { @class = "dropdown-item" })
                                            </div>
                                        </div>
                                    </td>
    
                                </tr>
    
                            }
                        </tbody>
                        <tfoot>
                            <tr class="text-primary">
                                <td>@Html.DisplayNameFor(model => model.cccClienteEdit.CCCClienteId)</td>
                                <td>@Html.DisplayNameFor(model => model.cccClienteEdit.Banco.Nombre)</td>
                                <td>@Html.DisplayNameFor(model => model.cccClienteEdit.iban)</td>
                                <td>@Html.DisplayNameFor(model => model.cccClienteEdit.BIC)</td>
                                <td>@Html.DisplayNameFor(model => model.cccClienteEdit.RefMandato)</td>
                                <td>@Html.DisplayNameFor(model => model.cccClienteEdit.FechaMandato)</td>
                                <td></td>
                            </tr>
                        </tfoot>
    
                    </table>
                }
    
                </div>
                <div class="tab-pane fade p-2 bg-light mb-3" id="profile" role="tabpanel" aria-labelledby="profile-tab">...</div>
                <div class="tab-pane fade p-2 bg-light mb-3" id="contact" role="tabpanel" aria-labelledby="contact-tab">...</div>
            </div>
        </div>
        @*Fin Tabs*@
    
    
    }
    
    <div>
    
    </div>
    
    @section Scripts {
        @Scripts.Render("~/bundles/jqueryval")
    }

    Por si acaso tiene algo que ver adjunto el modelview:

    public class ClienteEditViewModel
        {
            public ClienteEditViewModel()
            {
                cliente = new Cliente();
                cliente.CCCClientes = new List<CCCCliente>();
                cccClienteEdit = new CCCCliente();
            }
            
    
            public Cliente cliente { get; set; }
            public CCCCliente cccClienteEdit { get; set; }
    
        }

    ¿hay alguna forma de seguir el estado del modelo, para ver donde pierde los datos?

    Un Saludo.



    • Editado elturle domingo, 16 de diciembre de 2018 21:09 Añadir ModelView
    domingo, 16 de diciembre de 2018 19:34
  • porque no evaluas aplamar un poco los datos usando

    public class ClienteEditViewModel { public ClienteEditViewModel() { cliente = new Cliente(); CCCClientes = new List<CCCCliente>(); cccClienteEdit = new CCCCliente(); } public Cliente cliente { get; set; }

     public List<CCCCliente> cccClientes { get; set; } public CCCCliente cccClienteEdit { get; set; } }

    a ver si asi lo bindea

    El tema es que hay que analizar como llegan los datos en el post para realizar un binding por defecto

    Sino el otro camino es extender el binding y crear un custom

     Model Binding And Custom Model Binding in ASP.NET MVC

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    • Marcado como respuesta elturle lunes, 17 de diciembre de 2018 10:11
    domingo, 16 de diciembre de 2018 21:23
  • Muchas Gracias Leandro:

    Debe ser que no llega a tantos niveles. Bajandolo un nivel como me has comentado, funciona perfectamente.

    Un Saludo.

    lunes, 17 de diciembre de 2018 10:13