剃刀,两种形态,同一领域

Razor, two forms, same field

Form 1 是一组过滤器,"submit" 按钮将这些过滤器应用于 GET 方法。表格 2 是一组数据,"submit" 按钮保存该数据并通过 POST 方法继续筛选。过滤器选项来回传递 - 用户获取初始页面,可能会设置一些过滤器,根据控制器方法再次获取同一页面,然后用户可以修改一些数据并通过 POST 保存,然后 returns 返回相同过滤页面的 GET。

简化(更多可能无关紧要):

@model PagedList.IPagedList<xxx.Models.WttPlatformGridRow>

@using (Html.BeginForm("PlatformGridEdit", "Wtt", FormMethod.Get))
{
  @Html.CheckBox("ExcludeThrough", (bool)ViewBag.ExcludeThrough)
  <input type="submit" value="Filter" />
}

@using (Html.BeginForm("PlatformGridEdit", "Wtt", FormMethod.Post))
{
  @Html.Hidden("ExcludeThrough", (bool)ViewBag.ExcludeThrough)
  <input type="submit" value="Save" />
}

简化的控制器:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult PlatformGridEdit(List<WttPlatformGridRow> rows, bool? excludeThrough)
{ etc }

public ActionResult PlatformGridEdit(bool? excludeThrough)
{ etc }

显然,在 HTML 中将两个元素命名为相同的名称是非法的,而且无论如何都不起作用(C# 方法中的参数为 null)。

到目前为止我看到的答案建议使用一个包含所有数据的 BeginForm。美好的。除了一个是 GET(没有数据更改)和一个是 POST(数据更改)。用户需要能够为过滤器添加书签,所以我无法将其全部作为 POST 处理,否则浏览器将询问用户是否可以重新提交表单数据。

我也在使用 IPagedList,它(据我所知)排除了使用带有列表字段的单个模型而不是使用 ViewBag。

另一种选择似乎是使用客户端脚本将值从一个字段复制到另一个字段。但是当两个客户端字段的控制器方法中的参数名称相同时,我不知道如何执行此操作。

请问最好的处理方法是什么?

我有一个解决方案,但我忍不住想一定有更好的方法。

FWIW,这就是我所做的。这两个字段的名称不同(但相似)。 "master" 版本(可见复选框)具有在提交时将值复制到 "slave" 版本(隐藏字段)的脚本。控制器方法采用 both 名称并决定哪个是相关的 - 一个或两个应该为 null,但两者都不应该有值,但我们会处理以防万一。

最后,控制器 returns 具有组合值的视图(使用 "master" 标识)。

查看 - 表单 1:

bool excludeThrough = ViewBag.ExcludeThrough != null ? ViewBag.ExcludeThrough : false;

@Html.CheckBox("ExcludeThrough", excludeThrough, new
{
    @class = "form-control",
    onchange = "document.getElementById('ExcludeThroughFilter').value = document.getElementById('ExcludeThrough').value;"
})

查看 - 表单 2:

@Html.Hidden("ExcludeThroughFilter", excludeThrough)

控制器:

public ActionResult PlatformGridEdit(..., bool? excludeThrough, bool? excludeThroughFilter)
{
    bool excThru = false;
    if (excludeThrough.HasValue) excThru = excludeThrough.Value;
    if (excludeThroughFilter.HasValue && excludeThroughFilter.Value) excThru = true;
    ...etc...
}