IList 绑定 Razor 页面

IList binding Razor Pages

正在尝试绑定 IList 以便我可以更新我拥有的字段。但是,最终得到一个带有 OnPostAsync 的空列表。不确定我错过了什么。

我的代码如下所示:

[BindProperty]
public IList<Runbook_Serverlist_Plus> RunbookServerListPlus { get; set; }

此列表使用以下代码填充 OnGetAsync 函数:

public async Task OnGetAsync()
{
   var listRunbookServerList = await _context.Runbook_Serverlist.ToListAsync();
   RunbookServerListPlus = listRunbookServerList.Select(item => new Runbook_Serverlist_Plus(item)).ToList();
}

因此,从我的模型中,我首先获得 IList,然后为 Runbook_Serverlist_Plus 创建一个新列表。 想法是有一种 Runbook_Serverlist 的基础 class,然后在上面放一个 Runbook_Serverlist_Plus,我可以在其中设置特定的字段,稍后我可以使用这些字段来更新某些字段。

查看下面的代码:

  public class Runbook_Serverlist_Plus
  {
    [BindProperty]
    public Runbook_Serverlist Bc {get; set; }

    public Runbook_Serverlist_Plus(Runbook_Serverlist bsBc)
    {
      Bc = bsBc;
      CheckCompleted = false;
    }
    
    public bool CheckCompleted { get; set; }
  }

在我的cshmtl中代码如下:

<form method="post">
<table class="table">
  <thead>
  <tr>
    <th>
      @Html.DisplayNameFor(model => model.RunbookServerListPlus[0].Bc.Servername)
    </th>
    <th>
      @Html.DisplayNameFor(model => model.RunbookServerListPlus[0].Bc.Status)
    </th>
    <th>
      @Html.DisplayNameFor(model => model.RunbookServerListPlus[0].Bc.Cluster)
    </th>
    <th>
      @Html.DisplayNameFor(model => model.RunbookServerListPlus[0].Bc.StatusChange)
    </th>
    <th>
      @Html.DisplayNameFor(model => model.RunbookServerListPlus[0].Bc.PreRun)
    </th>
    <th>
      @Html.DisplayNameFor(model => model.RunbookServerListPlus[0].Bc.Ordering)
    </th>
    <th></th>
  </tr>
  </thead>
  <tbody>
  @for (var i = 0; i < Model.RunbookServerListPlus.Count; i++)
  {
    var item = Model.RunbookServerListPlus[i];
    <tr>
      <td>
        @Html.DisplayFor(modelItem => item.Bc.Servername)
      </td>
      <td>
        @Html.DisplayFor(modelItem => item.Bc.Status)
      </td>
      <td>
        @Html.DisplayFor(modelItem => item.Bc.Cluster)
      </td>
      <td>
        @Html.DisplayFor(modelItem => item.Bc.StatusChange)
      </td>
      <td>
        @Html.DisplayFor(modelItem => item.Bc.PreRun)
      </td>
      <td>
        @Html.DisplayFor(modelItem => item.Bc.Ordering)
      </td>
      <td>
        <input hidden asp-for="@item.Bc.Servername" class="form-control" />
        <input asp-for="@item.CheckCompleted"  class="form-control"/>
      </td>
    </tr>
  }
  </tbody>
</table>
  <div class="form-group">
    <input type="submit" value="Update" class="btn btn-primary" />
  </div>
</form>

所以我有一个 CheckCompleted 项目的复选框,在执行 post 时,我希望看到所有已标记的复选框。 当我执行 submit/post 时,我希望 RunbookServerListPlus 被填充。然而,这个一直是空的。

我错过了什么?

Post 函数现在没有别的了:

      public async Task<IActionResult> OnPostAsync()
      {
        if (!ModelState.IsValid)
        {
          return Page();
        }

        return RedirectToPage("./Index");
      }

根据用于发出请求的 HTTP 动词,每个请求只会触发一个处理程序。 OnGet 在使用 HTTP Get 方法请求页面时执行。 OnPost由POST方法执行。

网络是无状态的。这意味着在一个请求上初始化的变量对另一个请求不可用。如果你想在 OnPost 方法中使用集合,你需要在 OnPost 处理程序中再次实例化它。

有关我网站的更多详细信息:https://www.learnrazorpages.com/razor-pages/handler-methods

首先,您可以添加隐藏输入来绑定模型数据,表单 post 将传递输入' value.And .net core bind model with name attribute.If 你想绑定数据列表,您需要将名称设置为 list[index].xxx.

如果你只想在检查CheckCompleted时传递Runbook_Serverlist_Plus,你可以使用js将隐藏输入的名称更改为正确的格式,然后形成post.Here是一个演示。

型号:

public class Runbook_Serverlist_Plus
    {
        [BindProperty]
        public Runbook_Serverlist Bc { get; set; }
        public Runbook_Serverlist_Plus(Runbook_Serverlist bsBc)
        {
            Bc = bsBc;
            CheckCompleted = false;
        }
        public Runbook_Serverlist_Plus()
        {
        }
        public bool CheckCompleted { get; set; }
    }
    public class Runbook_Serverlist
    {
        public string Servername { get; set; }
        public string Status { get; set; }
        public string Cluster { get; set; }
        public string StatusChange { get; set; }
        public string PreRun { get; set; }
        public string Ordering { get; set; }


    }

cshtml:

<form method="post">
    <table class="table">
        <thead>
            <tr>
                <th>
                    @Html.DisplayNameFor(model => model.RunbookServerListPlus[0].Bc.Servername)
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.RunbookServerListPlus[0].Bc.Status)
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.RunbookServerListPlus[0].Bc.Cluster)
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.RunbookServerListPlus[0].Bc.StatusChange)
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.RunbookServerListPlus[0].Bc.PreRun)
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.RunbookServerListPlus[0].Bc.Ordering)
                </th>
                <th></th>
            </tr>
        </thead>
        <tbody>
            @for (var i = 0; i < Model.RunbookServerListPlus.Count; i++)
            {
                var item = Model.RunbookServerListPlus[i];
                <tr>
                    <td>
                        @Html.DisplayFor(modelItem => item.Bc.Servername)
                    </td>
                    <td>
                        @Html.DisplayFor(modelItem => item.Bc.Status)
                    </td>
                    <td>
                        @Html.DisplayFor(modelItem => item.Bc.Cluster)
                    </td>
                    <td>
                        @Html.DisplayFor(modelItem => item.Bc.StatusChange)
                    </td>
                    <td>
                        @Html.DisplayFor(modelItem => item.Bc.PreRun)
                    </td>
                    <td>
                        @Html.DisplayFor(modelItem => item.Bc.Ordering)
                    </td>
                    <td>
                        <input asp-for="@item.CheckCompleted" class="form-control" name="RunbookServerListPlus[index].CheckCompleted" />
                        <input hidden asp-for="@item.Bc.Servername" class="form-control" name="RunbookServerListPlus[index].Bc.Servername" />
                        <input hidden asp-for="@item.Bc.Status" class="form-control" name="RunbookServerListPlus[index].Bc.Status" />
                        <input hidden asp-for="@item.Bc.Cluster" class="form-control" name="RunbookServerListPlus[index].Bc.Cluster" />
                        <input hidden asp-for="@item.Bc.StatusChange" class="form-control" name="RunbookServerListPlus[index].Bc.StatusChange" />
                        <input hidden asp-for="@item.Bc.PreRun" class="form-control" name="RunbookServerListPlus[index].Bc.PreRun" />
                        <input hidden asp-for="@item.Bc.Ordering" class="form-control" name="RunbookServerListPlus[index].Bc.Ordering" />

                    </td>
                </tr>
            }
        </tbody>
    </table>
    <div class="form-group">
        <input type="submit" value="Update" class="btn btn-primary" />
    </div>
</form>
<script>
    $("form").submit(function () {
        var index = 0;
        $("tbody tr").each(function () {
            var lasttd = $(this).find('td:last-child');
            
            if (lasttd.find("input")[0].checked) {
                lasttd.find("input").each(function () {
                    $(this).attr("name", $(this).attr("name").replace("index",index));
                })
                index++;
            }
        })
    })
</script>

cshtml.cs(我用假数据测试):

[BindProperty]
        public List<Runbook_Serverlist_Plus> RunbookServerListPlus { get; set; }
        public void OnGet()
        {
            RunbookServerListPlus = new List<Runbook_Serverlist_Plus> {
                new Runbook_Serverlist_Plus { Bc = new Runbook_Serverlist { Cluster = "c1", Ordering = "1", PreRun="p1", Servername="sname1", Status="status1", StatusChange="statuschange1" } },
                new Runbook_Serverlist_Plus { Bc = new Runbook_Serverlist { Cluster = "c2", Ordering = "2", PreRun="p2", Servername="sname2", Status="status2", StatusChange="statuschange2" } },
                new Runbook_Serverlist_Plus { Bc = new Runbook_Serverlist { Cluster = "c3", Ordering = "3", PreRun="p3", Servername="sname3", Status="status3", StatusChange="statuschange3" } }

            };
        }
        public async Task<IActionResult> OnPostAsync()
        {
            if (!ModelState.IsValid)
            {
                return Page();
            }

            return RedirectToPage("./Index");
        }

结果:

更新(传递整个列表):

首先把第一个demo中的js去掉

然后像这样改变 td:

<td>
                    <input asp-for="@item.CheckCompleted" class="form-control" name="RunbookServerListPlus[@i].CheckCompleted" />
                    <input hidden asp-for="@item.Bc.Servername" class="form-control" name="RunbookServerListPlus[@i].Bc.Servername" />
                    <input hidden asp-for="@item.Bc.Status" class="form-control" name="RunbookServerListPlus[@i].Bc.Status" />
                    <input hidden asp-for="@item.Bc.Cluster" class="form-control" name="RunbookServerListPlus[@i].Bc.Cluster" />
                    <input hidden asp-for="@item.Bc.StatusChange" class="form-control" name="RunbookServerListPlus[@i].Bc.StatusChange" />
                    <input hidden asp-for="@item.Bc.PreRun" class="form-control" name="RunbookServerListPlus[@i].Bc.PreRun" />
                    <input hidden asp-for="@item.Bc.Ordering" class="form-control" name="RunbookServerListPlus[@i].Bc.Ordering" />

                </td>

结果:

检查传递给处理程序的数据: