将窗体发布后操作中更改的值传播到视图

页面创建日期 :

环境

Visual Studio
  • Visual Studio 2022
ASP.NET Core
  • 6.0 MVC

它适用于其他环境,但您发布的代码是在上述框架中创建的。

你正在做的

尝试编写一个简单的程序,"开机自检您在屏幕上输入的文本,并将收到的文本作为新结果返回到同一屏幕"。

代码

该基础是创建新的 MVC 项目,并从那里添加代码。 有关整个配置,请参阅此处的代码。

模型(视图模型)

为视图和操作之间的交互创建以下模型: ResultValue 有两个,但我想在视图中显示两个结果,所以我准备了两个。

SampleViewModel

namespace PostValueChange.Models
{
  public class SampleViewModel
  {
    /// <summary>入力値を受け取るプロパティ。</summary>
    public string? InputValue { get; set; }

    /// <summary>結果を出力するプロパティ。</summary>
    public string? ResultValue1 { get; set; }

    /// <summary>結果を出力するプロパティ。</summary>
    public string? ResultValue2 { get; set; }
  }
}

行动

在 GET 中显示视图,接受在开机自检中输入的文本,然后处理并返回结果。

HomeController

// 省略

namespace PostValueChange.Controllers
{
  public class HomeController : Controller
  {
    // 省略

    [HttpGet]
    public IActionResult Sample() => View();

    [HttpPost]
    public IActionResult Sample(SampleViewModel model)
    {
      if (ModelState.IsValid == false) View(model);
      model.ResultValue1 = model.InputValue + " テキストを追加1";
      model.ResultValue2 = model.InputValue + " テキストを追加2";
      return View(model);
    }
  }
}

视图

基于操作和模型创建视图。

当我单击更新按钮时 ResultValue1 ,我尝试显示 和 ResultValue2 ,但每个按钮都显示在"输入文本"和"div 标记中"中。

Sample.cshtml

@model PostValueChange.Models.SampleViewModel

@{
  ViewData["Title"] = "Sample";
}

<h1>Sample</h1>

<h4>SampleViewModel</h4>
<hr />
<div class="row">
  <div class="col-md-4">
    <form asp-action="Sample" >
      <div asp-validation-summary="ModelOnly" class="text-danger"></div>
      <div class="form-group">
        <label asp-for="InputValue" class="control-label"></label>
        <input asp-for="InputValue" class="form-control" />
        <span asp-validation-for="InputValue" class="text-danger"></span>
      </div>
      <div class="form-group">
        <input type="submit" value="更新" class="btn btn-primary" />
      </div>
      <div class="form-group">
        <label asp-for="ResultValue1" class="control-label"></label>
        <input asp-for="ResultValue1" class="form-control" />
        <span asp-validation-for="ResultValue1" class="text-danger"></span>
      </div>
      <div>@Model?.ResultValue2</div>
    </form>
  </div>
</div>

<div>
  <a asp-action="Index">前の画面に戻る</a>
</div>

@section Scripts {
  @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

Index.cshtmlSample 添加链接,以便可以从 转换到 。

Index.cshtml

@{
  ViewData["Title"] = "Home Page";
}

<div class="text-center">
  <h1 class="display-4">Welcome</h1>
  <p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
</div>

<a asp-action="Sample">Sample</a>    @* 追加 *@

更新 POST 处理接收的模型不会反映在视图输入等中。

运行上面编写的代码,然后尝试从 InputValue 示例屏幕输入 并更新 。

由于 ResultValue1 操作端将 值设置为 和 ResultValue2 返回,因此最初假定同时显示两者, div 但实际上仅显示在标记中设置的 2。

为模型状态设置的值优先

当从客户端开机自检输入值时,该值将设置为参数的模型变量, ControllerBase.ModelState 但其他值将设置为其他值。 然后,使用设置为 的值验证 ModelState 输入的值。 ModelState.IsValid 这也是我们能够做出判断的原因。 如果在调试时在断点处停止处理,则可以看到内容。

如果最初将值返回给视图, return View(model); 则按 如下所述,但ModelState 如果 设置为 ,则 ModelState 的值优先并返回到视图。

ModelState 设置为 的值是输入和发送的值,例如视图的输入,因此在 InputValue模型中,设置 ResultValue1 的状态为 。 因此,ResultValue1ModelState 值优先,ModelState 而 未 ResultValue2 设置为 的 值显示在视图中。

将值返回给视图以覆盖模型值

如上所述 ModelState ,设置为 的值将优先返回到视图,因此,如果删除设置为 相反 ModelState 的值,则模型的值将返回到视图。

您可以通过 ModelState 调用 来擦除 具有的所有值,如下所示 ModelState.Clear()

[HttpPost]
public IActionResult Sample(SampleViewModel model)
{
  if (ModelState.IsValid == false) View(model);

  // ModelState の値を消してモデルの値をビューに返却できるようにする
  ModelState.Clear();

  // ビューに返す値を設定する
  model.ResultValue1 = model.InputValue + " テキストを追加1";
  model.ResultValue2 = model.InputValue + " テキストを追加2";

  return View(model);
}

ModelState 也执行验证过程,因此在ModelState.Clear 调用 时,请确保 ModelState.IsValid 在 之后阅读 。

这将确保结果正确显示,如下所示:

ModelState.Clear 由于调用 方法时所有值都将消失,因此可以通过指定模型的属性名称来单独擦除该值,如下所示:

[HttpPost]
public IActionResult Sample(SampleViewModel model)
{
  if (ModelState.IsValid == false) View(model);

  // ModelState の値を消してモデルの値をビューに返却できるようにする
  ModelState.Remove(nameof(model.ResultValue1));

  // ビューに返す値を設定する
  model.ResultValue1 = model.InputValue + " テキストを追加1";
  model.ResultValue2 = model.InputValue + " テキストを追加2";

  return View(model);
}