將表單發佈後操作中更改的值傳播到檢視

頁面創建日期 :

環境

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);
}