Razor Pages でPOSTで画面遷移するとHTTP 400エラーが発生し画面遷移できない - ASP.NET Core

Razor Pages でポストで画面遷移しようとするとHTTP 400エラーが発生し画面遷移できない現象について紹介します。

現象の確認

Razor PagesにSubmitボタンなどを配置しPOSTで遷移する動作を実装して実行すると、HTTP 400エラーが発生し、ページ遷移できない場合があります。


サブミットボタンをクリックして遷移しようとするとHTTP 400エラーが発生します。


下記のメッセージが表示されます。
エラーメッセージ
このページは現在機能していません
HTTP ERROR 400

不具合1

コード

問題が発生するRazor Pagesのcshtmlコードは下記です。
@page "/Button"
@model SimpleButton.ButtonModel
@{
  Layout = null;
}
<!DOCTYPE html>
<html>
<head>
  <meta name="viewport" content="width=device-width" />
  <title>Button1</title>
</head>
<body>
  <div>Button Demo</div>
  <form method="post">
    <input type="submit" value="Button1" />
  </form>
</body>
</html>

原因

タグヘルパーが無いため、RequestVerificationTokenが送信されず、クロスサイト要求偽造チェックでNGとなり、400エラーが発生します。

対処法1:タグヘルパーの追加

@addTagHelper ディレクティブを追記して、タグヘルパーを有効にします。
修正後のコード
@page "/Button"
@model SimpleButton.ButtonModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@{
  Layout = null;
}
<!DOCTYPE html>
<html>
<head>
  <meta name="viewport" content="width=device-width" />
  <title>Button1</title>
</head>
<body>
  <div>Button Demo</div>
  <form method="post">
    <input type="submit" value="Button1" />
  </form>
</body>
</html>

参考:出力されるHTMLの違い

タグヘルパーが有効な場合とそうでない場合の出力されるHTMLの違いを確認します。
タグヘルパーが無い場合
<!DOCTYPE html>
<html>
<head>
  <meta name="viewport" content="width=device-width" />
  <title>Button1</title>
</head>
<body>
  <div>Button Demo</div>
  <form method="post">
    <input type="submit" value="Button1" />
  </form>
</body>
</html>
タグヘルパーが有効な場合
<!DOCTYPE html>
<html>
<head>
  <meta name="viewport" content="width=device-width" />
  <title>Button1</title>
</head>
<body>
  <div>Button Demo</div>
  <form method="post">
    <input type="submit" value="Button1" />
  <input name="__RequestVerificationToken" type="hidden" value="CfDJ8EL5y-BpEXFPhNBo25u1uGcl5v21mFISY00dX0plQh_JTMueLrfallMN8JixLkfqNaqlkHW2ZoaCg6iXe3dsXTrDoUxAQyY5zGxbsbdGAo_pa4HIPJK7FydXUnZ2mmsbATIQNf0xMh3IsSCmldj8Tig" /></form>
</body>
</html>

タグヘルパーが有効な場合は __RequestVerificationToken のhidden フィールドが追加されていることがわかります。

対処法2:タグヘルパーを利用せずに、RequestVerificationTokenを送信する

@Html.AntiForgeryToken() を利用するとタグヘルパーを利用せずに、RequestVerificationTokenを送信できます。
詳しくはこちらの記事を参照してください。

不具合2

コード

別のパターンの問題のあるコードです。
Button.cshtml
@page "/Button"
@model SimpleButtonBindProperty.ButtonModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@{
  Layout = null;
}
<!DOCTYPE html>
<html>
<head>
  <meta name="viewport" content="width=device-width" />
  <title>Button</title>
</head>
<body>
  <div>Button Demo</div>
  <form method="post" asp-antiforgery="false">
    Code:<input type="text" asp-for="data.Code"/><br/>
    Name:<input type="text" asp-for="data.Name" /><br />
    <input type="submit" value="Button1" />
  </form>
</body>
</html>
Button.cshtml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace SimpleButtonBindProperty
{
  public class ButtonModel : PageModel
  {
    [BindProperty]
    public SimpleModel data { get; set; }

    public void OnGet()
    {

    }
    public IActionResult OnPost()
    {
      return RedirectToPage("/ButtonResult",new { name= data.Name, code=data.Code });
    }
  }
}

原因

asp-antiforgery="false" が指定されており、クロスサイト要求偽造が無効になっていますが、 ページモデル側では[IgnoreAntiforgeryToken]属性が設定されておらず、POST時にRequestVerificationTokenが送信されず、 クロスサイト要求偽造チェックでNGとなり、400エラーが発生します。

対処法1: asp-antiforgery="false" を外す

asp-antiforgery="false" を削除し、クロスサイト要求偽造を有効にします。

対処法2: ページモデルクラスにIgnoreAntiforgeryToken属性を追加する

ページモデルクラスにIgnoreAntiforgeryToken属性を追加し、クロスサイト要求偽造のRequestVerificationTokenが無くても動作する設定にします。 詳細はこちらの記事を参照してください。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace SimpleButtonBindProperty
{
  [IgnoreAntiforgeryToken]
  public class ButtonModel : PageModel
  {
    [BindProperty]
    public SimpleModel data { get; set; }

    public void OnGet()
    {

    }
    public IActionResult OnPost()
    {
      return RedirectToPage("/ButtonResult",new { name= data.Name, code=data.Code });
    }
  }
}

対処法3: タグヘルパーを利用せずにRequestVerificationTokenを追加する

@Html.AntiForgeryToken() を利用するとタグヘルパーを利用せずに、RequestVerificationTokenを送信できます。
詳しくはこちらの記事を参照してください。
著者
iPentecのメインプログラマー
C#, ASP.NET の開発がメイン、少し前まではDelphiを愛用
最終更新日: 2022-06-04
作成日: 2020-01-07
iPentec all rights reserverd.