【问题标题】:Why does the model property data change when posting?为什么发布时模型属性数据会发生变化?
【发布时间】:2019-03-27 22:04:41
【问题描述】:

OnGet() 使用来自AspNetUsers 的数据填充UnapprovedApplications。 此时用户 ID 是正确的。

c4d69cbe-436e-4d74-bc7d-c4a99a8cbf34
e184da25-687b-4e51-9f1d-c3a93a732ec1

OnPostAsync() 然而,返回用户 ID 为

20b6af04-ecb5-49c0-b4e4-bdb172bd19c7
5a61fbce-4c69-4a15-be66-725c5ab4b884

为什么UnapprovedApplications 中的数据会发生变化? 如何防止这些数据发生变化?

一个模型ReviewApplicationModel是这样构造的

[BindProperty]
        public IList<ApplicationUser> UnapprovedApplications { get; set; }

        public void OnGet(string returnUrl = null)
        {
            ReturnUrl = returnUrl;
            UnapprovedApplications = new List<ApplicationUser>();
            foreach (var user in userManager.Users.Where(x => !x.Approved))
            {
                System.Diagnostics.Debug.WriteLine(user.Id);
                UnapprovedApplications.Add(user);
            }
        }

        public async Task<IActionResult> OnPostAsync()
        {
            if (!ModelState.IsValid)
            {
                return Page();
            }
            foreach (var user in UnapprovedApplications)
                System.Diagnostics.Debug.WriteLine(user.Id);
            return RedirectToPage();
        }

有观点

@page
@model ReviewApplicationsModel
@{
    ViewData["Title"] = "Review Applications";
    ViewData["ActivePage"] = ManageNavPages.ReviewApplications;
}

<h4>@ViewData["Title"]</h4>
<div class="row">
    <div class="col-md-6">
        <form asp-route-returnUrl="@Model.ReturnUrl" method="post">
            <button type="submit" class="btn btn-primary">Approve Selected Applications</button>
            <table class="table">
                <thead>
                    <tr>
                        <th>
                            @Html.DisplayNameFor(x => x.UnapprovedApplications.FirstOrDefault().Id)
                        </th>
                        <th>
                            @Html.DisplayNameFor(x => x.UnapprovedApplications.FirstOrDefault().Organization)
                        </th>
                        <th>
                            @Html.DisplayNameFor(x => x.UnapprovedApplications.FirstOrDefault().FEIEIN)
                        </th>
                        <th>
                            @Html.DisplayNameFor(x => x.UnapprovedApplications.FirstOrDefault().State)
                        </th>
                        <th>
                            @Html.DisplayNameFor(x => x.UnapprovedApplications.FirstOrDefault().PrincipalCity)
                        </th>
                        <th>
                            @Html.DisplayNameFor(x => x.UnapprovedApplications.FirstOrDefault().PhoneNumber)
                        </th>
                        <th>
                            Approved
                        </th>
                        <th></th>
                    </tr>
                </thead>
                <tbody>
                    @for (var i = 0; i < Model.UnapprovedApplications.Count(); i++)
                    {
                        <tr>
                            <td>@Model.UnapprovedApplications[i].Id</td>
                            <td>@Model.UnapprovedApplications[i].Organization</td>
                            <td>@Model.UnapprovedApplications[i].FEIEIN)</td>
                            <td>@Model.UnapprovedApplications[i].State</td>
                            <td>@Model.UnapprovedApplications[i].PrincipalCity</td>
                            <td>@Model.UnapprovedApplications[i].PhoneNumber</td>
                            <td>
                                <input asp-for="@Model.UnapprovedApplications[i].Approved" class="form-control" />
                                <span asp-validation-for="@Model.UnapprovedApplications[i].Approved" class="text-danger"></span>
                            </td>
                        </tr>
                    }
                </tbody>
            </table>
        </form>
    </div>
</div>

@section Scripts {
    <partial name="_ValidationScriptsPartial" />
}

【问题讨论】:

  • 请使用 Chrome 或 Firefox 中的开发者工具向我们展示正在发布到服务器的有效负载。
  • UnapprovedApplications [0] .Approved:真__RequestVerificationToken:CfDJ8O-HFbOstWtHoJ33 - d61DaNVv4NbYn8Sdo0l8dua4MXKn0AHsRjYs8I4tBwPAzbiEz0BX3_pw1KSrf_3DHR1Bp22bYg3G0ZMvyc2uv7sQCkxscx5dpKM_bKEnjje5vnhPFzGfIQAJ8vWtC_LJTSSBr4rLNA_qVWz3cn4jRKOEwtYJTKArMrGx-d4lEJ1IdW3Q UnapprovedApplications [0] .Approved:假UnapprovedApplications [1] .Approved:假应该它不被张贴真假?
  • HTTP 是无状态的 - 为什么 UnapprovedApplications 在一个请求 GET 中会与您的 POST 相同?你正在迭代不同的东西。我不认为你甚至POSTing 回来,等等(在你的代码中看到,你可以在你对有效负载的评论中看到)。
  • 也许我需要一些时间才能真正理解 HTTP。一切都很好,直到我决定要使用集合。您能否提供一个链接到有关在 aspnetcore 中使用集合的教程?
  • 等待@EdSF。我不明白你在告诉我什么。我GET 用户,将其放入一个集合中,然后视图显示所有数据……POST 如何不知道来自同一模型的数据?使用InputModel 的所有其他页面都没有问题。只有在尝试使用集合时才会出现此问题。此外,不可能在带有集合的视图中使用foreach。出于某种原因,我必须使用for 循环。我知道我在这里犯了一个错误,我不想说语言中存在错误。我希望有人能正确回答这个问题。

标签: c# asp.net asp.net-mvc razor


【解决方案1】:

这将是一个正在寻求解决此线程的独白。

我发现 IdentityUser 有一个生成 Guid 的默认构造函数。 发生的情况是客户端缺少模型数据,并且不同的用户 ID 不同,因为正在生成模型数据,就好像他们是新用户一样。

我发现了@Forty-2 发布的此信息 Pass an entire model on form submission

模型将完整地传递给控制器​​,但 不受输入或隐藏字段约束的属性值将 迷路了。

您必须在客户端绑定表单中的属性, 或在服务器端重新获取实体。

您似乎在要求类似@Html.HiddenFor(m => m.Model),这是不可能的。对不起

要记住一件事,如果您有大量隐藏字段,您可能 向视图发送比您真正需要的更多的数据。考虑 使用视图模型

我将实现整个聚合用户对象的 ViewModel 以尝试保留通过 GET 检索的数据,以便可以通过 POST 保存编辑后的数据。

好的,实际上我只是在表单中绑定了必要的数据,一切都按预期工作。

这里有一个解决方案

[AllowAnonymous]
    public class ReviewApplicationsModel : PageModel
    {
        readonly UserManager<ApplicationUser> userManager;

        public ReviewApplicationsModel(UserManager<ApplicationUser> userManager)
        {
            this.userManager = userManager;
        }

        public string ReturnUrl { get; set; }

        [BindProperty]
        public ObservableCollection<ApplicationUser> UnapprovedApplications { get; set; }

        public void OnGet(string returnUrl = null)
        {
            ReturnUrl = returnUrl;
            UnapprovedApplications = new ObservableCollection<ApplicationUser>();
            foreach (var user in userManager.Users.Where(x => !x.Approved))
                UnapprovedApplications.Add(user);
        }

        public async Task<IActionResult> OnPostAsync(string returnUrl = null)
        {
            ReturnUrl = returnUrl;
            if (!ModelState.IsValid)
                return Page();
            foreach (var user in UnapprovedApplications.Where(x => x.Approved))
            {
                var tmp = await userManager.FindByIdAsync(user.Id);
                tmp.Approved = true;
                await userManager.UpdateAsync(tmp);
            }
            return RedirectToPage();
        }
    }
@page
@model ReviewApplicationsModel
@{
    ViewData["Title"] = "Review Applications";
    ViewData["ActivePage"] = ManageNavPages.ReviewApplications;
}

<h4>@ViewData["Title"]</h4>
<div class="row">
    <form method="post">
        <div class="col-md-auto">
            <button type="submit" class="btn btn-primary">Approve Selected Applications</button>
            <table class="table">
                <thead>
                    <tr>
                        <th hidden>@Html.DisplayNameFor(x => x.UnapprovedApplications.FirstOrDefault().Id)</th>
                        <th>@Html.DisplayNameFor(x => x.UnapprovedApplications.FirstOrDefault().Organization)</th>
                        <th>@Html.DisplayNameFor(x => x.UnapprovedApplications.FirstOrDefault().FEIEIN)</th>
                        <th>@Html.DisplayNameFor(x => x.UnapprovedApplications.FirstOrDefault().State)</th>
                        <th>@Html.DisplayNameFor(x => x.UnapprovedApplications.FirstOrDefault().Approved)</th>
                    </tr>
                </thead>
                <tbody>
                    @for (var i = 0; i < Model.UnapprovedApplications.Count(); i++)
                    {
                    <tr>
                        <td hidden><input asp-for="UnapprovedApplications[i].Id" class="form-control" hidden /></td>
                        <td><input asp-for="UnapprovedApplications[i].Organization" class="form-control" disabled /></td>
                        <td><input asp-for="UnapprovedApplications[i].FEIEIN" class="form-control" disabled /></td>
                        <td><input asp-for="UnapprovedApplications[i].State" class="form-control" disabled /></td>
                        <td><input asp-for="UnapprovedApplications[i].Approved" class="form-control" /></td>
                    </tr>
                    }
                </tbody>
            </table>
        </div>
    </form>
</div>

@section Scripts {
    <partial name="_ValidationScriptsPartial" />
}

必须有一种更灵活的方式来做到这一点,我希望有一天能发现它,但现在可行

【讨论】:

    猜你喜欢
    • 2020-11-06
    • 2018-08-08
    • 1970-01-01
    • 2019-05-23
    • 2012-01-28
    • 2013-09-14
    • 2020-08-25
    • 1970-01-01
    • 2018-12-13
    相关资源
    最近更新 更多