Razor Pagesでマルチバイト文字を含むURLにリダイレクトすると例外が発生する - ASP.NET Core

Razor Pagesでマルチバイト文字を含むURLにリダイレクトすると例外が発生する現象と対処法を紹介します。

現象の確認

下記のRazor PagesのASP.NET Core Webアプリケーションを作成します。(.NET 6 を利用します。)

コード

遷移元のRazorPageです。
main-url-param.cshtml
@page
@model RedirectMultibyteUrl.Pages.main_paramModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@{
}
<html>
<head>

  <script type="text/javascript">
    function buttonClick()
    {
      var elem = document.getElementById('text1');
      document.location.href = "dest-url-param?query=" + elem.value;
    }
  </script>
</head>
<body>
  <h2>マルチバイト文字列のURLリダイレクトのデモ</h2>
  <form method="post">
    <input id="text1" type="text" asp-for="textbox1" />
    <input type="submit" value="Form Submit" asp-page-handler="Proc" />
  </form>
</body>
</html>
main-url-param.cshtml.cs
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace RedirectMultibyteUrl.Pages
{
  public class main_paramModel : PageModel
  {

    [BindProperty]
    public string textbox1 { get; set; }

    public IActionResult OnPostProc()
    {
      return Redirect(Url.Content("~/dest-url-param?query=" + textbox1));
    }
  }
}
遷移先のRazorPageです。
dest-url-param.cshtml
@page
@model RedirectMultibyteUrl.Pages.destModel
@{
}
<html>
    <head></head>
    <body>
        <p>リダイレクト先ページ</p>
        <p>@Model.query</p>
    </body>
</html>
dest-url-param.cshtml.cs
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace RedirectMultibyteUrl.Pages
{
  public class destModel : PageModel
  {
    [BindProperty(SupportsGet = true)]
    public string query { get; set; }
  }
}

Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
var app = builder.Build();

if (!app.Environment.IsDevelopment()) {
  app.UseExceptionHandler("/Error");
  app.UseHsts();
}
app.UseHttpsRedirection();
app.UseRouting();
app.MapRazorPages();

app.Run();

実行結果

プロジェクトを実行し(アプリケーションルートURL)/main-url-param のURLにアクセスします。下図のページが表示されます。


テキストボックスに "penguin" の文字列を入力しテキストボックス右側のボタンをクリックします。


リダイレクト先ページに遷移します。ページにパラメーターとして渡された "penguin" の文字列が表示されます。


元のページに戻り、テキストボックスに "ぺんぎん" の文字列を入力します。テキストボックス右側のボタンをクリックします。~


マルチバイト文字列が入力された場合は、下図の例外が発生します。


エラーメッセージ
An unhandled exception occurred while processing the request.
InvalidOperationException: Invalid non-ASCII or control character in header: 0x307A
Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpHeaders.ThrowInvalidHeaderCharacter(char ch)

このエラーで表示されている 0x307A の文字は の文字になります。入力された "ぺんぎん" の文字列の1文字目の文字が non-ASCII キャラクターであるため、例外が発生します。

対処法

マルチバイト文字列をURLに設定する場合は、URLエンコードをして設定します。
URLエンコードはSystem.Net.WebUtillity.UrlEncode() メソッドを利用します。詳細についてはこちらの記事を参照してください。
main-url-param.cshtml.cs
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace RedirectMultibyteUrl.Pages
{
  public class main_paramModel : PageModel
  {

    [BindProperty]
    public string textbox1 { get; set; }

    public IActionResult OnPostProc()
    {
      return Redirect(Url.Content("~/dest-url-param?query=" + System.Net.WebUtility.UrlEncode(textbox1)));
    }
  }
}

実行結果

上記のコードに編集したプロジェクトを実行し (アプリケーションルートURL)/main-url-param のURLにアクセスします。テキストボックスに "ぺんぎんクッキー" の文字rつを入力し、 右側のボタンをクリックします。


例外が発生せずにリダイレクト先ページに遷移します。ページにパラメーターとして渡された "ぺんぎんクッキー" の文字列が表示されます。


マルチバイト文字列のURLにリダイレクトできる処理を実装できました。
著者
iPentecのメインプログラマー
C#, ASP.NET の開発がメイン、少し前まではDelphiを愛用
最終更新日: 2024-01-24
作成日: 2022-01-03
iPentec all rights reserverd.