2

I have a view with a list of items that among their properties have a list of items (in View asp.net core).

I use a generic list to have common properties that I use in the view.

The ViewModels are these:

public class AgaqEleViewModel
{        
    public int CodEle { get; set; }

    public int AbrEle { get; set; }

    public string Valor { get; set; }

    ...
}

public class AgaqViewModel
{
    [Required(ErrorMessageResourceType = typeof(AguasResx.DataAnnotations), ErrorMessageResourceName = nameof(AguasResx.DataAnnotations.Required))]
    public int Hoja { get; set; } // Key Id compossed
    
    [Required(ErrorMessageResourceType = typeof(AguasResx.DataAnnotations), ErrorMessageResourceName = nameof(AguasResx.DataAnnotations.Required))]
    public DateTime FechaTomaAq { get; set; }
    
    public float? ProfmuestraM { get; set; }

    ...


    // List test
    public List<AgaqEleViewModel> AgaqEle { get; set; }


    ...
            
}

public class GenericListViewModel<T>
{

    public RespViewModel Resp { get; set; }

    public List<T> ItemsList { get; set; }


    public GenericListViewModel()
    {

    }

    public GenericListViewModel(RespViewModel resp, List<T> genericList)
    {
        Resp = resp;
        ItemsList = genericList;
    }

}

My Razor View is this:

@model GenericListViewModel<AgaqViewModel>

@{
// get max number of columns of different elements 
int numColElements = Model.ItemsList.Select(s => s.AgaqEle.Count).Max();
}


<form asp-action="AgaqLoaded" method="post" id="agaqExcelForm">

    @if(Model.Resp.XXX)
    {
        ...
    }
    
    <table class="table table-bordered table-sm table-striped">
        <thead>
            <tr>
                @* header columns *@
                <th title="@Literals.Hoja">@Literals.Hoja</th>
                ...

                @* create elements columns header´s *@
                @for(int i = 0; i < numColElements; i++)
                {
                    <th>@Literals.Element</th>
                }
                ...


        <tbody>
            // iterate each item in Model list
            @for (var i = 0; i < Model.ItemsList.Count(); i++)
            {               
                <tr>                    
                    <td class="">
                        <input asp-for="@Model.ItemsList[i].Hoja" type="hidden" />
                        @Model.ItemsList[i].Hoja
                    </td>
                    <td>
                        <input asp-for="@Model.ItemsList[i].FechaTomaAq" type="hidden" />
                        @Model.ItemsList[i].FechaTomaAq
                    </td>
                    ...

                    // iterate each list elements in each item in Model list
                    @for(int j = 0; j < numColElements; j++)
                        {
                            <td>                                
                                <input asp-for="@Model.ItemsList[i].AgaqEle[j].CodEle" type="hidden" />
                                <input asp-for="@Model.ItemsList[i].AgaqEle[j].AbrEle" type="hidden" />
                                <input asp-for="@Model.ItemsList[i].AgaqEle[j].Valor" type="hidden" />
                                ...
                                @elemAgaq.AbrEle: @elemAgaq.Valor
                            </td>                           
                        }
            }
...
<tfoot>
<button id="btnLoad" type="submit" class="btn btn-sm btn-primary"><i class="fa fa-upload"></i>&nbsp;@AguasLiterals.LoadData</button>
    ...
</form>

and my Controller is this:

[HttpPost("{controller}/{action}/")]
public async Task<IActionResult> AgaqLoaded(GenericListViewModel<AgaqViewModel> listToLoad)
{   
    // save 
    foreach (AgaqViewModel agaqEx in listToLoad.ItemsList)
    {
        AgaqDto saveAgaq = null;
        AgaqDto agaq = _mapper.Map<AgaqDto>(agaqEx);
            
        // save Agaq
        saveAgaq = await _service.SetAgaqAsync(agaq);
        ...

The generated HTML code is:

<td>
    <input type="hidden" data-val="true" data-val-range="El valor ..." data-val-range-max="9999" data-val-range-min="1" data-val-required="Este campo es obligatorio." id="ItemsList_0__Hoja" name="ItemsList[0].Hoja" value="1921">
    1921
</td>
<td>
    <input type="hidden" data-val="true" data-val-required="Este campo es obligatorio." id="ItemsList_0__FechaTomaAq" name="ItemsList[0].FechaTomaAq" value="20/07/2021 0:00:00">
    20/07/2021 0:00:00 
</td>


<td>
    <input type="hidden" data-val="true" data-val-required="The CodEle field is required." id="ItemsList_0__AgaqEle_0__CodEle" name="ItemsList[0].AgaqEle[0].CodEle" value="3">
    <input type="hidden" id="ItemsList_0__AgaqEle_0__AbrEle" name="ItemsList[0].AgaqEle[0].AbrEle" value="Na">
    <input type="hidden" id="ItemsList_0__AgaqEle_0__Valor" name="ItemsList[0].AgaqEle[0].Valor" value="48">
    ...
    Na: 48
</td>
<td>
    <input type="hidden" data-val="true" data-val-required="The CodEle field is required." id="ItemsList_0__AgaqEle_1__CodEle" name="ItemsList[0].AgaqEle[1].CodEle" value="3">
    <input type="hidden" id="ItemsList_0__AgaqEle_1__AbrEle" name="ItemsList[0].AgaqEle[1].AbrEle" value="Ca">
    <input type="hidden" id="ItemsList_0__AgaqEle_1__Valor" name="ItemsList[0].AgaqEle[1].Valor" value="16">
    ...
    Ca: 16
</td>

The objects arrive correctly to the view and the generated HMTL is apparently correct. (The rest of the items/elements have the correct numbering: ItemsList_1__AgaqEle_0__CodEle, ItemsList_1__AgaqEle_0__AbrEle ... ItemsList_7__AgaqEle_0__CodEle ...)

When in the view I comment out the part of the elements (second loop, asp-for hidden properties) inside each item in the list, I get it correctly.

enter image description here

But if I don't comment the elements, although the HTML is apparently correct, the post request call arrives null without any item or elements.

enter image description here

I have several "simple" lists of complex elements that work fine, but this list composed of items with a list of elements I can't binding it.

What am I doing wrong?

I've tried removing the generic viewmodel and leaving it as a list of items, I've tried using list[i][j] or list[i].[j] and everything I could think of but nothing works? Any ideas? Thanks.

7
  • By testing your code snapshot, it works fine. ItemsList[i].AgaqEle[j] is the correct way for model binding. Maybe your project contains any other code you do not share, and not sure why you use two @for (var i = 0; i < Model.ItemsList.Count(); i++) loop here. Suggest you can share your whole razor view. Commented Apr 20, 2022 at 5:17
  • The two @for loops (var i = 0; i < Model.ItemsList.Count(); i++) was a copy/paste error in the post, I have corrected it and added comments and another part of the code to make it more understandable (the list of items inside the list of items I show in columns dynamically, because they can have different number of items). Commented Apr 20, 2022 at 7:05
  • The rest of the view has no strange things (at least apparently) I don't copy the whole view because it is very long, but if it is necessary I put it. When commenting the elements inside the item the binding is done correctly, that's what I don't understand because in theory it is done correctly. Commented Apr 20, 2022 at 7:08
  • Yes. What you added does not affect model binding. It still works fine with model binding in my project. Do you just use form submit to the backend? Or you extra use ajax? Commented Apr 20, 2022 at 7:11
  • Only submit de form post to backend Commented Apr 20, 2022 at 7:27

1 Answer 1

2

In the end, the problem was not the binding of the properties, but rather the fact that the information was not arriving because of the large volume of information (as it was a list of items with a list of elements for each item).

Instead of giving an error with information, the input parameter of the binding simply arrived null.

To solve it we have added in the startup.cs, in the ConfigureServices part:

services.Configure<FormOptions>(options =>
{
    options.ValueCountLimit = int.MaxValue;
});

I hope it helps someone else.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.