asp.net 控制器 post 请求中的核心绑定为空(视图中包含内部元素列表的列表)

asp.net core binding null in controller post request (list with inside elements lists in view)

我有一个包含项目列表的视图,在它们的属性中有一个项目列表(在视图 asp.net 核心中)。

我使用通用列表来获得我在视图中使用的通用属性。

ViewModels 是这些:

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

}

我的 Razor View 是这样的:

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

我的控制器是这样的:

[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);
        ...

生成的HTML代码为:

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

对象正确到达视图并且生成的 HMTL 显然是正确的。 (其余 items/elements 的编号正确:ItemsList_1__AgaqEle_0__CodEle、ItemsList_1__AgaqEle_0__AbrEle ... ItemsList_7__AgaqEle_0__CodEle ...)

当我在视图中注释掉列表中每个项目内的元素部分(第二个循环,asp-用于隐藏属性)时,我得到了正确的。

但是,如果我不注释元素,虽然 HTML 显然是正确的,但 post 请求调用到达 null,没有任何项目或元素。

我有几个“简单”的复杂元素列表,它们工作正常,但这个列表由带有我无法绑定的元素列表的项目组成。

我做错了什么?

我试过删除通用视图模型并将其保留为项目列表,我试过使用 list[i][j] 或 list[i].[j] 以及我能想到的所有方法,但是什么都没用? 有什么想法吗?谢谢。

最后,问题不在于属性的绑定,而是由于信息量大导致信息没有到达的事实(因为它是项目列表以及每个项目的元素列表)。

绑定的输入参数没有给出错误信息,而是简单地到达了null

为了解决这个问题,我们在 startup.csConfigureServices 部分添加了:

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

希望对其他人有所帮助。