英文:
Data binding overwriting changes made to list in Razor Pages
问题
I have an application with a list of a complex type.
I can (seemingly) successfully delete items from the list (the "laptop bag" has been deleted from the list) Deleting "Laptop bag" -
The collection after deleting
However, the generated HTML has the wrong value
for some reason the description is different ONLY in the "hiddenfor" element.
What is really weird is that "Model.HardwareList[i].Description" is different when I print it normally compared to using the hiddenfor.
Whenever I do another post, my list is no longer correct.
If there's anything I can do to elaborate please say so.
It is not a mismatch of id when deleting, I have double-checked to see if the id is correct and I also manually checked the collection after the deletion to see if it's correct.
PageModel
public class HardwareModel : PageModel
{
[BindProperty]
public List<Hardware> HardwareList { get; set; } = new List<Hardware>();
[BindProperty]
public List<string> HardwareNames { get; set; } = new List<string>();
[BindProperty]
public string ChosenNewHardware { get; set; }
[BindProperty]
public int HardwareIdxToDelete { get; set; }
public void OnGet()
{
GetData();
}
public void OnPost()
{
GetData();
}
public void OnPostAddNew()
{
if (ChosenNewHardware != null && !HardwareList.Any(h => h.Description == ChosenNewHardware))
{
HardwareList.Add(new Hardware
{
Description = ChosenNewHardware,
UnitPrice = 10
});
}
GetData();
}
public void OnPostRemove()
{
var hw = HardwareList[HardwareIdxToDelete];
HardwareList.Remove(hw);
GetData();
}
public void GetData()
{
HardwareNames.Add("Dell P2419H");
HardwareNames.Add("Laptop bag");
HardwareNames.Add("Backpack");
HardwareNames.Add("Mouse");
}
}
cshtml:
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-html -->
@page
@model IctRequest.Pages.HardwareModel
@section Styles {
<link href="@Url.Content("~/css/form.css")" rel="stylesheet" type="text/css" />
}
<div class="form-body">
<div class="form-holder" style="display:block; min-height:0px">
<div class="form-content">
<div class="form-items">
@{
for (int i = 0; i < Model.HardwareList.Count; i++)
{
<br />
<div class="row rounded bg-secondary p-3 align-items-center">
<div class="col-md-1">
<form method="post" asp-page-handler="Remove">
<div id="hiddenParams">
@for (int h = 0; h < Model.HardwareList.Count; h++)
{
@Html.HiddenFor(m => @Model.HardwareList[h].Description)
@Html.HiddenFor(m => @Model.HardwareList[h].Quantity)
@Html.HiddenFor(m => @Model.HardwareList[h].UnitPrice)
@Html.HiddenFor(m => @Model.HardwareList[h].Remarks)
}
</div>
<input data-val="true" id="HardwareIdxToDelete" name="HardwareIdxToDelete" type="hidden" value="@i">
<button type="submit" class="btn btn-danger">X</button>
</form>
</div>
<form method="post" asp-page-handler="OnPost" class="col-md-11 row">
<div class="col-md-3 m-auto"><h4 style="color:#fff">@Model.HardwareList[i].Description</h4>@Html.HiddenFor(m => Model.HardwareList[i].Description)</div><div class="vr p-0"></div>
<div class="col-md-2 m-auto">@Html.TextBoxFor(m => Model.HardwareList[i].Quantity,new { @class="form-control m-0 p-1" })</div><div class="vr p-0"></div>
<div class="col-md-1 m-auto">€@Model.HardwareList[i].UnitPrice @Html.HiddenFor(m => Model.HardwareList[i].UnitPrice)</div><div class="vr p-0"></div>
<div class="col-md-1 m-auto">€0</div><div class="vr p-0"></div>
<div class="col-md-4 m-auto">@Html.TextBoxFor(m => Model.HardwareList[i].Remarks, new { @class="form-control m-0" })</div>
<button type="submit" hidden>Save</button>
</form>
</div>
}
}
</div>
</div>
</div>
</div>
<div class="d-flex flex-column align-items-end pr-5">
<form method="post" asp-page-handler="AddNew">
@{
var usedNames = new List<string>();
for (int h = 0; h < Model.HardwareList.Count; h++)
{
usedNames.Add(Model.HardwareList[h].Description);
@Html.HiddenFor(m => @Model.HardwareList[h].Description)
@Html.HiddenFor(m => @Model.HardwareList[h].Quantity)
@Html.HiddenFor(m => @Model.HardwareList[h].UnitPrice)
@Html.HiddenFor(m => @Model.HardwareList[h].Remarks)
}
<select class="child_input" id="ChosenNewHardware" name="ChosenNewHardware">
@for (int n = 0; n < Model.HardwareNames.Count; n++)
{
if (!usedNames.Contains(Model.HardwareNames[n]))
{
<option>@Model.HardwareNames[n]</option>
}
else
{
<option disabled>@Model.HardwareNames[n]</option>
}
}
</select>
//@Html.DropDownListFor(app => Model.ChosenNewHardware, new SelectList(Model.HardwareNames), new { @class = "child_input" })
}
<button type="submit">Add hardware</button>
</form>
</div>
<!-- end snippet -->
Model:
public class Hardware
{
[Key]
public int Id { get; set; }
[Required]
public Request Request { get; set; }
[Required]
public string TopdeskId { get; set; }
public string Description { get; set; }
[Required]
public int Quantity { get; set; }
[Required]
public double UnitPrice { get; set; }
public string Remarks { get; set; }
}
英文:
I have an application with a list of a complex type.
I can (seemingly) succesfully delete items from the list (the "laptop bag" has been deleted from the list) Deleting "Laptop bag" -
The collection after deleting
However, the generated html has the wrong value
for some reason the description is different ONLY in the "hiddenfor" element.
What is really weird is that "Model.HardwareList[i].Description" is different when I print it normally compared to using the hiddenfor.
Whenever I do another post, my list is no longer correct.
If there's anything I can do to elaborate please say so.
It is not a mismatch of id when deleting, I have doublechecked to see if the id is correct and I also manually checked the collection after the deletion to see if it's correct.
PageModel
public class HardwareModel : PageModel
{
[BindProperty]
public List<Hardware> HardwareList { get; set; } = new List<Hardware>();
[BindProperty]
public List<string> HardwareNames { get; set; } = new List<string>();
[BindProperty]
public string ChosenNewHardware { get; set; }
[BindProperty]
public int HardwareIdxToDelete { get; set; }
public void OnGet()
{
GetData();
}
public void OnPost()
{
GetData();
}
public void OnPostAddNew()
{
if (ChosenNewHardware != null && !HardwareList.Any(h => h.Description == ChosenNewHardware))
{
HardwareList.Add(new Hardware
{
Description = ChosenNewHardware,
UnitPrice = 10
});
}
GetData();
}
public void OnPostRemove()
{
var hw = HardwareList[HardwareIdxToDelete];
HardwareList.Remove(hw);
GetData();
}
public void GetData()
{
HardwareNames.Add("Dell P2419H");
HardwareNames.Add("Laptop bag");
HardwareNames.Add("Backpack");
HardwareNames.Add("Mouse");
}
}
cshtml:
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-html -->
@page
@model IctRequest.Pages.HardwareModel
@section Styles {
<link href="@Url.Content("~/css/form.css")" rel="stylesheet" type="text/css" />
}
<div class="form-body">
<div class="form-holder" style="display:block; min-height:0px">
<div class="form-content">
<div class="form-items">
@{
for (int i = 0; i < Model.HardwareList.Count; i++)
{
<br />
<div class="row rounded bg-secondary p-3 align-items-center">
<div class="col-md-1">
<form method="post" asp-page-handler="Remove">
<div id="hiddenParams">
@for (int h = 0; h < Model.HardwareList.Count; h++)
{
@Html.HiddenFor(m=> @Model.HardwareList[h].Description)
@Html.HiddenFor(m=> @Model.HardwareList[h].Quantity)
@Html.HiddenFor(m=> @Model.HardwareList[h].UnitPrice)
@Html.HiddenFor(m=> @Model.HardwareList[h].Remarks)
}
</div>
<input data-val="true" id="HardwareIdxToDelete" name="HardwareIdxToDelete" type="hidden" value="@i">
<button type="submit" class="btn btn-danger">X</button>
</form>
</div>
<form method="post" asp-page-handler="OnPost" class="col-md-11 row">
<div class="col-md-3 m-auto"><h4 style="color:#fff">@Model.HardwareList[i].Description</h4>@Html.HiddenFor(m => Model.HardwareList[i].Description)</div><div class="vr p-0"></div>
<div class="col-md-2 m-auto">@Html.TextBoxFor(m => Model.HardwareList[i].Quantity,new { @class="form-control m-0 p-1" })</div><div class="vr p-0"></div>
<div class="col-md-1 m-auto">€@Model.HardwareList[i].UnitPrice @Html.HiddenFor(m => Model.HardwareList[i].UnitPrice)</div><div class="vr p-0"></div>
<div class="col-md-1 m-auto">€0</div><div class="vr p-0"></div>
<div class="col-md-4 m-auto">@Html.TextBoxFor(m => Model.HardwareList[i].Remarks, new { @class="form-control m-0" })</div>
<button type="submit" hidden>Save</button>
</form>
</div>
}
}
</div>
</div>
</div>
</div>
<div class="d-flex flex-column align-items-end pr-5">
<form method="post" asp-page-handler="AddNew">
@{
var usedNames = new List<string>();
for (int h = 0; h < Model.HardwareList.Count; h++)
{
usedNames.Add(Model.HardwareList[h].Description);
@Html.HiddenFor(m=> @Model.HardwareList[h].Description)
@Html.HiddenFor(m=> @Model.HardwareList[h].Quantity)
@Html.HiddenFor(m=> @Model.HardwareList[h].UnitPrice)
@Html.HiddenFor(m=> @Model.HardwareList[h].Remarks)
}
<select class="child_input" id="ChosenNewHardware" name="ChosenNewHardware">
@for (int n = 0; n < Model.HardwareNames.Count; n++)
{
if (!usedNames.Contains(Model.HardwareNames[n]))
{
<option>@Model.HardwareNames[n]</option>
}
else
{
<option disabled>@Model.HardwareNames[n]</option>
}
}
</select>
//@Html.DropDownListFor(app => Model.ChosenNewHardware, new SelectList(Model.HardwareNames), new { @class = "child_input" })
}
<button type="submit">Add hardware</button>
</form>
</div>
<!-- end snippet -->
Model:
public class Hardware
{
[Key]
public int Id { get; set; }
[Required]
public Request Request { get; set; }
[Required]
public string TopdeskId { get; set; }
public string Description { get; set; }
[Required]
public int Quantity { get; set; }
[Required]
public double UnitPrice { get; set; }
public string Remarks { get; set; }
}
答案1
得分: 0
也许你只是从HardwareList
中删除了它,但该值仍然存在于ModelState
中,因此会出现匹配错误。
请尝试清除ModelState
:
public void OnPostRemove()
{
var hw = HardwareList[HardwareIdxToDelete];
HardwareList.Remove(hw);
ModelState.Clear();
GetData();
}
测试结果:
英文:
Maybe you just removed it from the HardwareList
, but the value still exists in ModelState
, so there will be a match error.
Please try to clear ModelState
:
public void OnPostRemove()
{
var hw = HardwareList[HardwareIdxToDelete];
HardwareList.Remove(hw);
ModelState.Clear();
GetData();
}
Test Result:
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论