[解決]ASP.NET MVCでHiddenの値が変わらない時にすること

2021年5月28日金曜日

ASP.NET C#

t f B! P L

POSTされたHIDDENの値が書き換わらない…

ASP.NET MVCでPOSTされたHiddenの値を、Contoller(コントローラー)の処理で書き換えても変更内容がHTML側に反映されない。

例えば、次のようにPOST時にHiddenValueのプロパティを書き換えるプログラムを書いても、出力されるHTMLは書き換え前のHiddenの値となる。

cshtml

<form method="post">
  <input asp-for="HiddenValue" type="hidden" />
  <button type="submit">送信</button>
</form>

Contoller

public IActionResult Index()
{
    var vm = new MyViewModel { HiddenValue = "最初のHIddenの値" };
    return View(vm);
}

[HttpPost]
public IActionResult Index(MyViewModel vm)
{
    vm.HiddenValue = "変更後のHiddenの値";
    return View(vm);
}

▪️ 出力されるHTML
<form method="post">
  <input value="最初のHIddenの値" type="hidden" />
  <button type="submit">送信</button>
</form>

ModelStateをクリアすると値が反映される

この動きはバグではなく、ModelState ディクショナリの仕様に関連した動きです。

ASP.NET MVCでは、POSTされた値はModelState ディクショナリに格納されます。そしてasp-for="xxx"などで使用するタグヘルパーは、まずModelState ディクショナリに該当のキーの値があるか調べて、あればそれを表示し、無かった時に初めてモデル(今回の例ではMyViewModel)の値を表示します。

このように、HiddenなどのPOSTされる値については、ModelState ディクショナリの値が優先して表示されますため、今回の用件であるContollerで設定した内容でHiddenの内容を書き換えたい場合は、ModelState ディクショナリの内容をクリアしてあげれば反映されます。

ModelStateのクリア

ModelState ディクショナリをクリアする方法には、次の2つの方法があります。

1つ目はModelState全体をクリアする方法です。この方法の場合、値を書き換えたいHidden以外のすべてのPOSTデータが、ModelStateからクリアされます。

[HttpPost]
public IActionResult Index(MyViewModel vm)
{
    ModelState.Clear();
    vm.HiddenValue = "変更後のHiddenの値";
    return View(vm);
}

2つ目は指定したキーのみ、ModelStateから削除する方法である。指定したキーのデータのみ削除され、その他のPOSTデータはModelStateに残る。

[HttpPost]
public IActionResult Index(MyViewModel vm)
{
    ModelState.Remove("HiddenValue")
    vm.HiddenValue = "変更後のHiddenの値";
    return View(vm);
}
スポンサーリンク

QooQ