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> @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.cs 的 ConfigureServices 部分添加了:
services.Configure<FormOptions>(options =>
{
options.ValueCountLimit = int.MaxValue;
});
希望对其他人有所帮助。
我有一个包含项目列表的视图,在它们的属性中有一个项目列表(在视图 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> @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.cs 的 ConfigureServices 部分添加了:
services.Configure<FormOptions>(options =>
{
options.ValueCountLimit = int.MaxValue;
});
希望对其他人有所帮助。