0

I have a Index view calling a partial view where I list my model (an IEnumerable) and draw checkboxes to select some of the items to update.

I wrapped the partial view with a ajax form, to send the model (with the checked check boxes), but when it reach to the controller action "Enviar", the custom object parameter comes null

I don't know why, according some posts my code should be working, please, what I'm doing wrong?

Index View

@model IEnumerable<beDGRAIC.T_Sedd_Cuadro_Envio_Empresa>
.....
@Html.Partial("_ListaResumenCarga", Model)
.....

_ListaResumenCarga View

@model IEnumerable<beDGRAIC.T_Sedd_Cuadro_Envio_EmpresaViewModel>

@using (Ajax.BeginForm("Enviar", "Upload", new { @id = "FormCabecera" },
new System.Web.Mvc.Ajax.AjaxOptions()
{
    HttpMethod = "POST",
    InsertionMode = System.Web.Mvc.Ajax.InsertionMode.Replace,
    UpdateTargetId = "SeccionListado",
    OnSuccess = "RefrescaListado"
}))
{
    <table>
        <tbody>
            @if (Model != null)
            {
                foreach (var item in Model)
                {
                    <tr>
                        <td class="text-center">@Html.EditorFor(modelItem => item.Seleccionado, new { @checked = "checked" })</td>
                        <td class="text-left">@Html.DisplayFor(modelItem => item.Categoria)</td>
                        <td class="text-left">@Html.DisplayFor(modelItem => item.Codigo)</td>
                        <td class="text-left">@Html.DisplayFor(modelItem => item.Nombre)</td>
                        <td class="text-center">@Html.DisplayFor(modelItem => item.Nro_Registros)</td>
                    </tr>
                    @Html.HiddenFor(modelItem => item.Seleccionado)
                    @Html.HiddenFor(modelItem => item.Id_Cuadro_Envio)
                }
            }
        </tbody>
    </table>
    <button type="submit">Enviar</button>
}

UploadController

public class UploadController : Controller
{
    [HttpPost]
    public ActionResult Enviar(IEnumerable<T_Sedd_Cuadro_Envio_EmpresaViewModel> lT_Sedd_Cuadro_Envio_EmpresaViewModel)
    {
        ....
        return View("Envios", vT_Sedd_Envio_Empresa);
    }
}

Model Class

[DataContract]
[Serializable]
public partial class T_Sedd_Cuadro_Envio_EmpresaViewModel : BEPaginacion
{
    [DataMember]
    public bool Id { get; set; }
    [DataMember]
    public bool Seleccionado { get; set; }
    [DataMember]  
    public int Id_Cuadro_Envio { get; set; }  
    [DataMember]  
    public int Id_Envio_Empresa { get; set; }  
    [DataMember]  
    public string Categoria { get; set; }  
    .... // more properties
}
culebrin
  • 125
  • 1
  • 15
  • 2
    You need to edit your question and remove all the irrelevant code! The basic problem is you partial is generating duplicate `id` (invalid html) and `name` attributes (so cannot bind to a collection). You need to use a `for` loop (the model needs to be `IList`) or a custom `EditorTemplate` for typeof `T_Sedd_Cuadro_Envio_Empresa`. Then you have `EditorFor()` for `Seleccionado` followed by a `HiddenFor()` for the same property - even if you name the controls property it will only ever post back the original value, not the edited value. –  Mar 13 '15 at 02:10
  • binding to a collection is a pain. consider having a per line form instead – Ewan Mar 13 '15 at 11:21
  • Thank you Stephen!, It worked!, the reason for post all my code was that I saw in other posts the users asked for that. If you want to, you can post your comment as answer to mark it as a solution... thank you very much – culebrin Mar 13 '15 at 14:15
  • 1
    @culebrin, I have taken the liberty of removing most of the code in your question, keeping only what is relevant. Please refer [How to create a Minimal, Complete, and Verifiable example](http://stackoverflow.com/help/mcve) –  Mar 14 '15 at 01:57
  • Thank you very much for that, but I have hard time to realize which part form my code was the relevant part of my error, that's why I decided put the hole code. Now I can analyze your edit to improve my future questions. Thanks a lot. – culebrin Mar 15 '15 at 17:37

1 Answers1

1

You use of a foreach loop in the partial is generating duplicate id (invalid html) and name attributes meaning it cant be bound to a collection. You need to use a for loop or a custom EditorTemplate for type of T_Sedd_Cuadro_Envio_EmpresaViewModel. In addition you are generating a both a checkbox and a hidden input for property Seleccionado

EditorTemplate /Views/Shared/EditorTempplates/T_Sedd_Cuadro_Envio_EmpresaViewModel.cshtml

@model T_Sedd_Cuadro_Envio_EmpresaViewModel
<tr>
  <td>
    @Html.CheckBoxFor(m => m.Seleccionado)</td> // do not set the checked attribute!
    @Html.HiddenFor(m => m.Id_Cuadro_Envio) // inside a td element
  </td>
  <td>@Html.DisplayFor(m => m.Categoria)</td>
  .... // other properties to display/edit
</tr>

Then in the partial

@model IEnumerable<beDGRAIC.T_Sedd_Cuadro_Envio_EmpresaViewModel>
@using (Ajax.BeginForm("Enviar", "Upload", ....))
{
  <table>
   <thead>
     .... // table headings
   </thead>
   <tbody>
     @EditorFor(m => m) // this will render all the rows
   </tbody>
  </table>
  <button type="submit">Enviar</button>
}

Side notes:

  1. A html helper binds to the value of a property (in you case bool Categoria) which mean that if the value of Categoria is true, the checkbox will be checked, otherwise it will unchecked. Do not try to set the checked attribute, and in any case it would not work because you have not used the overload correctly)
  2. An <input> is not a valid child of a <tr> element
  3. You have named you class T_Sedd_Cuadro_Envio_EmpresaViewModel suggesting its a view model, which clearly its not (before my edit it contained 17 properties, but you only use 6 in the view). A view model represents what you want to dislay/edit in a view - refer What is a viewmodel in mvc (and please, keep it simple, just EmpresaViewModel and public ActionResult Enviar(IEnumerable<EmpresaViewModel> model))
Community
  • 1
  • 1