ページ表示時に "System.NullReferenceException - Object reference not set to an instance of an object." エラーが発生する

Blazorアプリケーションでページ表示時に "System.NullReferenceException - Object reference not set to an instance of an object." エラーが発生する場合の原因と対処法を紹介します。

現象の確認

Blazorアプリケーションで、ページの表示時に以下のエラーが発生します。
エラーメッセージ
System.NullReferenceException
HResult=0x80004003
Message=Object reference not set to an instance of an object.

原因

いくつか原因は考えられますが、ページの表示時に出力する変数や変数のオブジェクトがnullになっている可能性が考えられます。

再現プログラム

コード

ASP.NET Coreアプリケーションを作成し、下記のファイル、コードを記述します。
Pages/ClassMemberOutputOnButtonClick.razor
@page "/ClassMemberOutputOnButtonClick"
<h3>ClassMemberOutputOnButtonClick</h3>

@code {
  MyClass mc;

  private void OnButtonClick()
  {
    mc = new MyClass(); 
  }
  
}
<buton onclick="OnButtonClick">Exec</buton>
<input class="ResultTextBox" type="text" ID="TextBox1" value="@mc.x" />
<input class="ResultTextBox" type="text" ID="TextBox2" value="@mc.y" />

<p>@mc.x</p>
<p>@mc.y</p>
Module/MyClass.cs
namespace ClassMemberOutput.Module
{
  public class MyClass
  {
    public int x { get { return ix * 2; } }
    public int y { get { return iy * 2; } }
    public int z { get { return iz * 2; } }

    private int ix;
    private int iy;
    private int iz;

    public MyClass()
    {
      ix = 2;
      iy = 4;
      iz = 8;
    }
  }
}
_Imports.razor
@using System.Net.Http
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.JSInterop
@using Module
_Host.cshtml
@page
@namespace  ClassMemberOutput
<!DOCTYPE html>
<html lang="ja">
<head>
</head>
<body>
    <app>
        @(await Html.RenderComponentAsync<App>(RenderMode.ServerPrerendered))
    </app>
    <script src="_framework/blazor.server.js"></script>
</body>
</html>
App.razor
<Router AppAssembly="@typeof(Program).Assembly">
    <Found Context="routeData">
        <RouteView RouteData="@routeData"/>
    </Found>
    <NotFound>
        <LayoutView>
            <p>Sorry, there's nothing at this address.</p>
        </LayoutView>
    </NotFound>
</Router>
Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
var app = builder.Build();

app.UseStaticFiles();
app.UseRouting();

app.UseEndpoints(endpoints =>
{
  endpoints.MapBlazorHub();
  endpoints.MapFallbackToPage("/_Host");
});

app.Run();

実行結果

アプリケーションを起動し、(アプリケーション ルートURL)/ClassMemberOutputOnButtonClick にアクセスすると、"System.NullReferenceException" 例外が発生し下図の状態になります。

解説

ClassMemberOutputOnButtonClick.razor ファイルで、codeブロックで、MyClass の宣言をしていますが、インスタンスが作成されるのは、OnButtonClick() メソッド内となります。 このため、ページ表示時には、MyClassのインスタンスオブジェクトが作成されておらず、変数 mc は nullの状態になっており、mc.x mc.y の値を表示するinputタグとpタグの部分で、 nullのmcオブジェクトを参照して、System.NullReferenceException のエラーが発生します。
Pages/ClassMemberOutputOnButtonClick.razor
@page "/ClassMemberOutputOnButtonClick"
<h3>ClassMemberOutputOnButtonClick</h3>

@code {
  MyClass mc;

  private void OnButtonClick()
  {
    mc = new MyClass(); 
  }
  
}
<buton onclick="OnButtonClick">Exec</buton>
<input class="ResultTextBox" type="text" ID="TextBox1" value="@mc.x" />
<input class="ResultTextBox" type="text" ID="TextBox2" value="@mc.y" />

<p>@mc.x</p>
<p>@mc.y</p>

対処法

ページの表示時にインスタンスオブジェクトを作成するロジックにします。
以下のコードに変更します。
Pages/ClassMemberOutputOnButtonClick.razor
@page "/ClassMemberOutputOnButtonClick"
<h3>ClassMemberOutputOnButtonClick</h3>

@code {
  MyClass mc = new MyClass(); 
}
<buton onclick="OnButtonClick">Exec</buton>
<input class="ResultTextBox" type="text" ID="TextBox1" value="@mc.x" />
<input class="ResultTextBox" type="text" ID="TextBox2" value="@mc.y" />

<p>@mc.x</p>
<p>@mc.y</p>
または、
Pages/ClassMemberOutputOnButtonClick.razor
@page "/ClassMemberOutputOnButtonClick"
<h3>ClassMemberOutputOnButtonClick</h3>

@code {
  MyClass mc;
  
  protected override void OnInitialized()
  {
    mc = new MyClass(); 
  }
}
<buton onclick="OnButtonClick">Exec</buton>
<input class="ResultTextBox" type="text" ID="TextBox1" value="@mc.x" />
<input class="ResultTextBox" type="text" ID="TextBox2" value="@mc.y" />

<p>@mc.x</p>
<p>@mc.y</p>

実行結果

変更後のコードでURLにアクセスすると、例外が発生せずにページが表示できます。

著者
iPentecのメインプログラマー
C#, ASP.NET の開発がメイン、少し前まではDelphiを愛用
最終更新日: 2022-05-31
作成日: 2022-05-31
iPentec all rights reserverd.