如何在 ASP.NET 核心视图中正确显示复选框表单控件?

How to properly display checkbox form controls in ASP.NET Core Views?

我有一个带有布尔值 属性 的模型,它将在我的视图中显示为一个复选框:

public class SomeModel
{
    public bool SomeProperty { get; set; }
}

我正在创建这样的视图:

<div class="form-check">
    <input asp-for="TestProperty" value="true" class="form-check-input" />
    <label class="form-check-label" asp-for="TestProperty"></label>
</div>

下面是浏览器中的 HTML 输出:

<div class="form-check">
    <input value="true" class="form-check-input" type="checkbox" data-val="true" data-val-required="The TestProperty field is required." id="TestProperty" name="TestProperty">
    <label class="form-check-label" for="TestProperty">TestProperty</label>
</div>

我可以看到下面隐藏的元素附加在表单的末尾:

<input name="TestProperty" type="hidden" value="false">

当我提交表单时,这是请求正文:

TestProperty: true
TestProperty: false

第一行中的值是复选框元素中的值,第二行是在控制器中接收时覆盖第一行值的隐藏元素的值。我注意到当我点击复选框时,隐藏输入的值没有改变。

想到的第一个解决方案是在输入值更改时通过 JavaScript 更新隐藏元素,这是不必要的。有什么办法可以摆脱这些隐藏的元素吗?或者我没有正确显示表单控件。我不确定。

更新

隐藏的输入元素由 razor 视图本身自动添加。虽然我使用的是 controllers/views 而不是 razor 视图,但我测试了 Enrico 的解决方案,结果是一样的。它仍然为复选框附加一个隐藏的输入元素:

您不需要手动添加隐藏的输入字段,或通过客户端 Javascript 代码与之交互。使用 ASP.NET 核心和 Razor 的方法是使用标签助手并让实际的 HTML 生成由 Razor 本身完成。

这是一个在页面输入模型中使用 Razor Pages 和单个布尔值的示例。我在 Visual Studio 2019 中使用了 ASP.NET 核心 3.1 和常用的 ASP.NET 核心 Web 应用程序模板。

这是页面模型:

public class TestFormModel : PageModel
  {
    private readonly ILogger _logger;

    public TestFormModel(ILogger<TestFormModel> logger)
    {
      _logger = logger;
    }

    [BindProperty]
    public InputModel Input { get; set; }

    public IActionResult OnGet()
    {
      this.Input = new TestFormModel.InputModel
      {
        ShowUsername = false
      };

      return this.Page();
    }

    public IActionResult OnPost() 
    {
      if (!this.ModelState.IsValid) 
      {
        return this.Page();
      }

      _logger.LogInformation("The posted value is: {Value}", this.Input.ShowUsername);

      return this.RedirectToPage("Index");
    }

    public class InputModel 
    {
      [Display(Name = "Show User Name")]
      public bool ShowUsername { get; set; }
    }
  }

这是关联的 Razor 视图:

@page
@model WhosebugTest.Pages.TestFormModel
@{
  ViewData["Title"] = "How to build a form with a checkbox";
}

<h1>@ViewData["Title"]</h1>

<form asp-page="TestForm">
  <div class="form-check">
    <input class="form-check-input" asp-for="Input.ShowUsername">
    <label class="form-check-label" asp-for="Input.ShowUsername"></label>
  </div>
  <button type="submit" class="btn btn-primary">Submit</button>
</form>

就是这样。您无需在表单中手动添加隐藏输入。您只需要使用正确的标签帮助,ASP.NET core 就会为您生成正确的表单和表单输入。

2021 年 8 月 2 日更新

有关工作示例,请参阅 this github repository

作为旁注,请考虑隐藏输入字段由 ASP.NET 核心自动添加,并且需要它才能 post 到服务器 Input.ShowUsername 的正确值当表单中的复选框未选中时

基本上在生成的 HTML 页面源中有 两个 表单输入用于 Input.ShowUsername。其中一个是 HTML 输入 type="checkbox",另一个是 HTML 输入 type="hidden"。它们的 name 属性值相同 (name="Input.ShowUsername"),而 value 属性对于复选框输入是 true,对于隐藏的是 false输入。

这是表单的 HTML 页面源代码(正是 ASP.NET core 3.1 生成它的方式):

<form action="/TestForm" method="post">
  <div class="form-check">
    <input class="form-check-input" type="checkbox" data-val="true" data-val-required="The Show User Name field is required." id="Input_ShowUsername" name="Input.ShowUsername" value="true">
    <label class="form-check-label" for="Input_ShowUsername">Show User Name</label>
  </div>
  <button type="submit" class="btn btn-primary">Submit</button>
  <input name="__RequestVerificationToken" type="hidden" value="CfDJ8AHG4SVs1BBFruMHNiza3QNKvHNf96d_oiz5J6n3eYuncnlFKqvL4x3G6jbAOmNfJjrwk_crqFN99kjZiBVoboFGd0VQIBlrvmp9fL6p8CMbiZ4f6Cf4rm3OpGZEZ_04UQQ5iuUi3nVjfIgfb5-vctw" />
  <input name="Input.ShowUsername" type="hidden" value="false">
</form>

选中表单中的复选框时,值 true 被 post 发送到服务器以获取名称 Input.ShowUsername,取消选中复选框时值 [=21] =] 已 post 发送到服务器以获取名称 Input.ShowUsername 这是有效的,因为未选中复选框的值未 post 发送到服务器 .

添加带有 type="hidden" 的输入是 post 复选框未选中时的默认值的常见模式,请参阅 here 了解有关方式的解释 HTML 复选框有效。

同样,所有这些都是由 ASP.NET 核心自动为您生成的:您只需定义页面输入模型并使用适当的 Razor 标签助手。