【问题标题】:Razor Collection binding malfunctionRazor Collection 绑定故障
【发布时间】:2020-03-30 09:54:21
【问题描述】:

我在使用 ASP.NET Core 3.1 网站时遇到了一个奇怪的问题。

我使用 Razor 生成的网页,并绑定来自 ViewModel 类的对象集合。它就像一个魅力,直到我从这个集合中删除这个对象之一。我可以看到该对象已正确删除到控制器中,更新的集合被发送到 Razor 引擎,并且 Razor 引擎将更新的集合插入到网页中。

但是,最终,浏览器收到了一个不正确的集合,其中包含已删除的项目并且缺少集合中的最后一个项目,尽管这不是控制器发送的内容有些东西在网页生成后修改了这个集合,我不知道是什么,我快疯了。

浏览器的缓存被禁用(我仔细检查了收到的 HTML 是否与显示的 HTML 匹配),我没有在 Razor 引擎之后运行任何定制的中间件,我没有任何客户端脚本,也没有AJAX,并且控制器只在请求时运行一次。

您对进一步的故障排除步骤有什么提示吗?我怎样才能深入到 ASP 引擎中找出这个 HTML 是在哪里修改的?

详细步骤:

  • FooView 初始化为 4 项,ID 从 1 到 4,名称 Foo1Foo2Foo3Foo4
  • 客户端点击Foo2删除按钮
  • FooController 处理请求,并更新现在包含 Id = {1,3,4}、Names={Foo1Foo3Foo4}的集合
  • FooController 将此集合发送到 Razor 引擎,通过插入断点,我可以评估插入了 Foo1、Foo3 和 Foo4,但没有插入 Foo2
  • 回到浏览器时,我在表格中看到Foo1Foo2Foo3Foo4 不见了。
public class FooVM
{
    public int Id { get; set; }
    public string Name { get; set; }

}

public class MasterViewModel
{
    public string OtherProperty1 { get; set; }
    public string OtherProperty2 { get; set; }

    private List<FooVM> Foos { get; set; }

}

public class FooController : Controller
{
    [HttpPost("Delete")]
    public IActionResult DeletePOST(MasterViewModel model, string deleteId) {
        if (int.TryParse(deleteId, out int id) && model.Foos.Any(x => x.Id == id)) {
                model.Foos.Remove(model.Foos.First(x => x.Id == id));
            }
            return View("FooView", model);
    }
}
<!-- language: html -->

//FooView.cshtml File Extract
@model MasterViewModel
<form asp-controller="FooController " asp-action="UpdatePOST" method="post" id="detailedform">
<table>
    <tbody>
        @for (int i = 0; i < Model.Foos.Count; i++) {

            <td nowrap="nowrap">
                <input asp-for="@Model.Foos[i].Id"  readonly/>
            </td>

            <td nowrap="nowrap">
                <input asp-for="@Model.Foos[i].Name" />
            </td>

            <td nowrap="nowrap" class="text-center">
                <button type="submit" asp-action="DeletePOST" name="deleteId" value="@Model.Foos[i].Id" style="background-color:transparent; border:none">
                    <i class="fa fa-times fa-2x" style="color:red"></i>
                </button>
            </td>
            </tr>
        }

</tbody>
</table>
</form>



【问题讨论】:

    标签: c# asp.net-core razor-pages


    【解决方案1】:

    经过长时间的调查,我发现在生成 Razor 页面时,Model 对象中的数据与 ViewData.ModelState 字典中的数据存在差异,我无法解释。 Model 对象包含更新的列表,而 ModelState 嵌入式字典包含旧的键/值对,引用提交的列表(未更新的列表)。

    在进行调试检查时,cshtml 文件 @Model.Foos[i].Name 变量显示正确的值,但似乎稍后计算的用于生成最终 HTML 的值取自 ModelState不匹配。

    这是一个错误吗?

    无论如何,我通过在生成视图之前将 ModelState.Clear() 添加到控制器中解决了这个问题。

    public class FooController : Controller
    {
        [HttpPost("Delete")]
        public IActionResult DeletePOST(MasterViewModel model, string deleteId) {
            if (int.TryParse(deleteId, out int id) && model.Foos.Any(x => x.Id == id)) {
                    model.Foos.Remove(model.Foos.First(x => x.Id == id));
                }
                ModelState.Clear();
                return View("FooView", model);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2011-04-06
      • 2021-04-09
      • 1970-01-01
      • 1970-01-01
      • 2014-05-29
      • 1970-01-01
      • 2017-04-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多