Odzwierciedlanie wartości zmienionej w akcji po opublikowaniu formularza w widoku

Data utworzenia strony :

środowisko

Visual Studio
  • Program Visual Studio 2022
Rdzeń ASP.NET
  • 6,0 MVC

Działa w środowiskach innych niż powyższe, ale opublikowany kod został napisany w powyższym frameworku.

Co zrobić

Spróbuj utworzyć prosty program, który mówi: "Opublikuj wpisany tekst na ekranie i zwróć przetworzony tekst na ten sam ekran jako nowy wynik".

kod

Podstawą jest stworzenie nowego projektu MVC, z którego dodajesz kod. Kod jest publikowany dla ogólnej konfiguracji, więc proszę się z nim zapoznać.

Model (viewmodel)

Utwórz następujący model interakcji widoku i akcji: ResultValue Są dwa, ale chciałem podać dwa wyniki w widoku, więc przygotowałem dwa.

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

akcja

To prosty proces: wyświetl widok, weź tekst wprowadzony w POST, przetwórz go i zwróć wynik.

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

widok

Tworzenie widoków na podstawie akcji i modeli.

Po kliknięciu ResultValue1 przycisku aktualizacji i ResultValue2 są wyświetlane, ale są wyświetlane odpowiednio w "tekście wejściowym" i "w znaczniku 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.cshtml Dodaj łącze, aby móc przejść z Sample do .

Indeks.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>    @* 追加 *@

Aktualizacja modelu otrzymanego w procesie POST nie wpływa na wprowadzanie widoku itp.

Uruchom kod utworzony powyżej, wprowadź go na InputValue ekranie Przykład i spróbuj zaktualizować.

Po stronie akcji, ResultValue1 ponieważ wartości są ustawione i ResultValue2 zwracane, zakłada się, że oba są pierwotnie wyświetlane, ale w rzeczywistości div wyświetlane są tylko 2 ustawione w tagu.

Wartość ustawiona na ModelState ma pierwszeństwo

Gdy klient POST wartość wejściową, wartość jest ustawiana na zmienną modelu argumentu ControllerBase.ModelState , ale wartość jest również ustawiana. Wprowadzona wartość jest ModelState następnie sprawdzana z wartością ustawioną na . ModelState.IsValid Dlatego jest osądzany. Podczas debugowania można sprawdzić zawartość, zatrzymując przetwarzanie w punkcie przerwania.

Jeśli pierwotnie chcesz zwrócić wartość do widoku, return View(model); możesz dołączyć , ale jeśli wartość jest ModelState ustawiona na ,ModelState wartość ma pierwszeństwo i jest zwracana do widoku.

ModelState Ponieważ wartość ustawiona na jest wartością wysłaną przez wprowadzenie widoku itp., W kategoriach InputValuemodelu, , jest ustawiona ResultValue1 . ResultValue1 W związku z tym wartość ma pierwszeństwo ModelState ,ModelState a wartość ustawiona w modelu, która nie ResultValue2 jest ustawiona na jest wyświetlana w widoku.

Aby zwrócić wartość do widoku na korzyść wartości modelu

ModelState Wartości ustawione tak, aby miały pierwszeństwo przed widokiem, więc jeśli ModelState usuniesz wartości ustawione na , wartość modelu zostanie zwrócona do widoku.

ModelState.Clear() Możesz usunąć wszystkie wartości, które mają, wywołując ModelState w następujący sposób:

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

ModelStatewykonuje również proces sprawdzania poprawności, więc pamiętajModelState.IsValid,ModelState.Clear aby przeczytać go po wywołaniu .

Po uruchomieniu wynik zostanie wyświetlony poprawnie w następujący sposób.

ModelState.Clear Ponieważ wszystkie wartości znikają po wywołaniu metody, możliwe jest również określenie nazwy właściwości modelu i wymazanie wartości pojedynczo w następujący sposób.

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