HTML として出力される日本語が実態参照(数値文字参照)にならないようにする

ページ作成日 :

環境

Visual Studio
  • Visual Studio 2019
ASP.NET Core
  • 3.1 (Razor ページ, MVC)

プログラムで動的に配置した日本語は実態参照として出力される

以下のように Index.cshtml に直接日本語を入力したものと ViewData を利用して日本語を出力したものを表示させてみます。

<!-- 省略 -->

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

<p>ここに固定文字列の日本語を表示させます。</p>
<p>@ViewData["Message"]</p>

プログラム側では ViewData に日本語を設定しておきます。

Index.cshtml.cs (Razor ページの場合)

// 省略

public class IndexModel : PageModel
{
  // 省略

  public void OnGet()
  {
    ViewData["Message"] = "ViewData から日本語を表示させます。";
  }
}

HomeController.cs (MVC の場合)

// 省略

public class HomeController : Controller
{
  // 省略

  public IActionResult Index()
  {
    ViewData["Message"] = "ViewData から日本語を表示させます。";
  }
}

デバッグ実行してみるとどちらも正しく日本語が表示されています。

しかし、Web ブラウザでページのソースを見てみると、ViewData で出力した日本語は実態参照(数値文字参照) で出力されていることが分かります。

実態参照(数値文字参照)とは英数字しか処理できない環境や特定の言語しか表示できない環境でも Unicode 文字を表現したい場合に使用される英数字による代替文字です。 例えば「あ」という文字は実態参照(数値文字参照)では「&#x3042;」として表示されます。

一般的な Web ブラウザは HTML に実態参照が含まれている場合でも正しくエンコードして文字を表示させているので、 利用者は実態参照に気づかない場合が多いです。

基本的には Web ブラウザで正しく表示されるのでこのままでも問題はないのですが、 出力される文字数が増えるのと、開発時に HTML を見たときに読みにくかったりするので次の方法でそのまま日本語で出力させることができます。

日本語を実態参照(数値文字参照)で出力されないようにする

Startup.cs ファイルに以下のようにコードを追加するだけです。

// 追加
using Microsoft.Extensions.WebEncoders;
using System.Text.Encodings.Web;
using System.Text.Unicode;

// 省略

public class Startup
{
  // 省略

  // このメソッドはランタイムによって呼び出されます。 このメソッドを使用して、コンテナーにサービスを追加します。
  public void ConfigureServices(IServiceCollection services)
  {
    // 省略

    // 全ての文字をが実態参照で出力されないようにする
    // 全てではなく特定の範囲のみをエンコードさせたくない場合は UnicodeRanges.All のプロパティを個別に設定します。
    services.Configure<WebEncoderOptions>(options =>
    {
      options.TextEncoderSettings = new TextEncoderSettings(UnicodeRanges.All);

      // 個別に設定する場合 (例)
      //options.TextEncoderSettings = new TextEncoderSettings(UnicodeRanges.Hiragana, UnicodeRanges.Katakana);
    });
  }

  // 省略
}

Startup.ConfigureServices メソッド内で services.Configure<WebEncoderOptions> メソッドを呼び出し、 options.TextEncoderSettingsTextEncoderSettings のインスタンスをセットします。

引数に UnicodeRanges.All をセットすると、全ての文字が実態参照に変換されずそのまま出力されるようになります。

変換させない範囲を個別に指定する場合は UnicodeRanges.All 以外の値を1つないし複数指定することになります。 ただ基本的には特別な理由がない限りは UnicodeRanges.All を指定してよいでしょう。

実際に実行して確認すると実態参照にはならずに直接日本語が出力されていることが分かります。