数据绑定在Razor页面中覆盖对列表所做的更改。

huangapple go评论65阅读模式
英文:

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

All seems well

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

All seems well

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&lt;Hardware&gt; HardwareList { get; set; } = new List&lt;Hardware&gt;();
[BindProperty]
public List&lt;string&gt; HardwareNames { get; set; } = new List&lt;string&gt;();
[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 &amp;&amp; !HardwareList.Any(h =&gt; 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(&quot;Dell P2419H&quot;);
HardwareNames.Add(&quot;Laptop bag&quot;);
HardwareNames.Add(&quot;Backpack&quot;);
HardwareNames.Add(&quot;Mouse&quot;);
}
}

cshtml:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-html -->

@page
@model IctRequest.Pages.HardwareModel
@section Styles {
&lt;link href=&quot;@Url.Content(&quot;~/css/form.css&quot;)&quot; rel=&quot;stylesheet&quot; type=&quot;text/css&quot; /&gt;
}
&lt;div class=&quot;form-body&quot;&gt;
&lt;div class=&quot;form-holder&quot; style=&quot;display:block; min-height:0px&quot;&gt;
&lt;div class=&quot;form-content&quot;&gt;
&lt;div class=&quot;form-items&quot;&gt;
@{
for (int i = 0; i &lt; Model.HardwareList.Count; i++)
{
&lt;br /&gt;
&lt;div class=&quot;row rounded bg-secondary p-3 align-items-center&quot;&gt;
&lt;div class=&quot;col-md-1&quot;&gt;
&lt;form method=&quot;post&quot; asp-page-handler=&quot;Remove&quot;&gt;
&lt;div id=&quot;hiddenParams&quot;&gt;
@for (int h = 0; h &lt; Model.HardwareList.Count; h++)
{
@Html.HiddenFor(m=&gt; @Model.HardwareList[h].Description)
@Html.HiddenFor(m=&gt; @Model.HardwareList[h].Quantity)
@Html.HiddenFor(m=&gt; @Model.HardwareList[h].UnitPrice)
@Html.HiddenFor(m=&gt; @Model.HardwareList[h].Remarks)
}
&lt;/div&gt;
&lt;input data-val=&quot;true&quot; id=&quot;HardwareIdxToDelete&quot; name=&quot;HardwareIdxToDelete&quot; type=&quot;hidden&quot; value=&quot;@i&quot;&gt;
&lt;button type=&quot;submit&quot; class=&quot;btn btn-danger&quot;&gt;X&lt;/button&gt;
&lt;/form&gt;
&lt;/div&gt;
&lt;form method=&quot;post&quot; asp-page-handler=&quot;OnPost&quot; class=&quot;col-md-11 row&quot;&gt;
&lt;div class=&quot;col-md-3 m-auto&quot;&gt;&lt;h4 style=&quot;color:#fff&quot;&gt;@Model.HardwareList[i].Description&lt;/h4&gt;@Html.HiddenFor(m =&gt; Model.HardwareList[i].Description)&lt;/div&gt;&lt;div class=&quot;vr p-0&quot;&gt;&lt;/div&gt;
&lt;div class=&quot;col-md-2 m-auto&quot;&gt;@Html.TextBoxFor(m =&gt; Model.HardwareList[i].Quantity,new { @class=&quot;form-control m-0 p-1&quot; })&lt;/div&gt;&lt;div class=&quot;vr p-0&quot;&gt;&lt;/div&gt;
&lt;div class=&quot;col-md-1 m-auto&quot;&gt;€@Model.HardwareList[i].UnitPrice @Html.HiddenFor(m =&gt; Model.HardwareList[i].UnitPrice)&lt;/div&gt;&lt;div class=&quot;vr p-0&quot;&gt;&lt;/div&gt;
&lt;div class=&quot;col-md-1 m-auto&quot;&gt;€0&lt;/div&gt;&lt;div class=&quot;vr p-0&quot;&gt;&lt;/div&gt;
&lt;div class=&quot;col-md-4 m-auto&quot;&gt;@Html.TextBoxFor(m =&gt; Model.HardwareList[i].Remarks, new { @class=&quot;form-control m-0&quot; })&lt;/div&gt;
&lt;button type=&quot;submit&quot; hidden&gt;Save&lt;/button&gt;
&lt;/form&gt;
&lt;/div&gt;
}
}
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;d-flex flex-column align-items-end pr-5&quot;&gt;
&lt;form method=&quot;post&quot; asp-page-handler=&quot;AddNew&quot;&gt;
@{
var usedNames = new List&lt;string&gt;();
for (int h = 0; h &lt; Model.HardwareList.Count; h++)
{
usedNames.Add(Model.HardwareList[h].Description);
@Html.HiddenFor(m=&gt; @Model.HardwareList[h].Description)
@Html.HiddenFor(m=&gt; @Model.HardwareList[h].Quantity)
@Html.HiddenFor(m=&gt; @Model.HardwareList[h].UnitPrice)
@Html.HiddenFor(m=&gt; @Model.HardwareList[h].Remarks)
}
&lt;select class=&quot;child_input&quot; id=&quot;ChosenNewHardware&quot; name=&quot;ChosenNewHardware&quot;&gt;
@for (int n = 0; n &lt; Model.HardwareNames.Count; n++)
{
if (!usedNames.Contains(Model.HardwareNames[n]))
{
&lt;option&gt;@Model.HardwareNames[n]&lt;/option&gt;
}
else
{
&lt;option disabled&gt;@Model.HardwareNames[n]&lt;/option&gt;
}
}
&lt;/select&gt;
//@Html.DropDownListFor(app =&gt; Model.ChosenNewHardware, new SelectList(Model.HardwareNames), new { @class = &quot;child_input&quot; })
}
&lt;button type=&quot;submit&quot;&gt;Add hardware&lt;/button&gt;
&lt;/form&gt;
&lt;/div&gt;

<!-- 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();
}

测试结果:

数据绑定在Razor页面中覆盖对列表所做的更改。

英文:

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:

数据绑定在Razor页面中覆盖对列表所做的更改。

huangapple
  • 本文由 发表于 2023年2月23日 21:45:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/75545676.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定