ASP.NET Core アプリケーションのRazor Pages でファイルをアップロードしても IFormFile オブジェクトがnull になってしまう - ASP.NET Core

ASP.NET Core アプリケーションのRazor Pages でファイルをアップロードしても IFormFile オブジェクトがnull になってしまう現象について紹介します。

概要

ファイルをアップロードするRazor Pages を作成し実行すると、ページモデルでファイルのデータを受け取る変数がnullになってしまいます。
補足
Razor Pages でファイルをアップロードするコードについてはこちらの記事も参照してください。

原因

いくつか原因がありますが、次のいずれかの可能性が高いです。
  • Razor Pages 側のFormタグに enctype="multipart/form-data" が指定されていない
  • IFormFile オブジェクトの変数がプロパティとして宣言されてない
  • IFormFile オブジェクトがプロパティとして宣言されているが、BindProperty 属性が付与されていない

現象 : enctype="multipart/form-data" が指定されていない場合

以下のコードの場合に発生します。
none-enctype.cshtml
@page
@model FileUpload.Pages.none_enctypeModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@{
}
<html>
<head>

</head>
<body>
  <form method="post">
    <div>ファイルのアップロード<input type="file" asp-for="FileData" /></div>
    <input type="submit" value="POST" />
  </form>
</body>
</html>
none-enctype.cshtml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Http;

namespace FileUpload.Pages
{
  public class none_enctypeModel : PageModel
  {
    [BindProperty]
    public IFormFile FileData { get; set; }

    public void OnGet()
    {
    }

    public IActionResult OnPost()
    {
      System.IO.Stream stream = FileData.OpenReadStream();
      byte[] buffer = new byte[stream.Length];
      stream.Read(buffer, 0, (int)stream.Length);

      System.IO.FileStream fs = new System.IO.FileStream(FileData.FileName, System.IO.FileMode.CreateNew);
      fs.Write(buffer, 0, buffer.Length);
      fs.Close();
      stream.Close();

      return RedirectToPage("/simple-upload-complete");
    }
  }
}

実行結果

プロジェクトを実行し"none-enctype"のRazor Pageを表示します。[ファイルの選択]ボタンをクリックしアップロードするファイルを 選択し、[POST]ボタンをクリックします。


FileData を参照する行でIFormFile オブジェクトのFileData変数がnullであるため例外が発生して停止します。

対処法

Razor PagesのFormタグに enctype="multipart/form-data" を指定します。
変更前
  <form method="post" enctype="multipart/form-data" >
    <div>ファイルのアップロード<input type="file" asp-for="FileData" /></div>
    <input type="submit" value="POST" />
  </form>
変更後
  <form method="post">
    <div>ファイルのアップロード<input type="file" asp-for="FileData" /></div>
    <input type="submit" value="POST" />
  </form>

現象 : IFormFile オブジェクトの変数がプロパティとして宣言されてない場合

以下のコードの場合に発生します。
none-enctype.cshtml
@page
@model FileUpload.Pages.none_enctypeModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@{
}
<html>
<head>

</head>
<body>
  <form method="post" enctype="multipart/form-data">
    <div>ファイルのアップロード<input type="file" asp-for="FileData" /></div>
    <input type="submit" value="POST" />
  </form>
</body>
</html>
none-enctype.cshtml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Http;

namespace FileUpload.Pages
{
  public class none_enctypeModel : PageModel
  {
    public IFormFile FileData;

    public void OnGet()
    {
    }

    public IActionResult OnPost()
    {
      System.IO.Stream stream = FileData.OpenReadStream();
      byte[] buffer = new byte[stream.Length];
      stream.Read(buffer, 0, (int)stream.Length);

      System.IO.FileStream fs = new System.IO.FileStream(FileData.FileName, System.IO.FileMode.CreateNew);
      fs.Write(buffer, 0, buffer.Length);
      fs.Close();
      stream.Close();

      return RedirectToPage("/simple-upload-complete");
    }
  }
}

実行結果

先の例と同様にファイルをアップロードすると、FileData を参照する行でIFormFile オブジェクトのFileData変数がnullであるため例外が発生して停止します。

対処法

ページオブジェクトの IFormFile の変数をプロパティで宣言します。
変更前l
  public IFormFile FileData;
変更後l
  [BindProperty]
  public IFormFile FileData { get; set; }

現象 : IFormFile オブジェクトがプロパティとして宣言されているが、BindProperty 属性が付与されていない場合

Razor Pages のFormタグには enctype="multipart/form-data" が指定されており、 ページモデルオブジェクトもFileDataはプロパティとして宣言されています。ただし、BindProperty 属性が指定されていません。
none-enctype.cshtml
@page
@model FileUpload.Pages.none_enctypeModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@{
}
<html>
<head>

</head>
<body>
  <form method="post" enctype="multipart/form-data">
    <div>ファイルのアップロード<input type="file" asp-for="FileData" /></div>
    <input type="submit" value="POST" />
  </form>
</body>
</html>
none-enctype.cshtml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Http;

namespace FileUpload.Pages
{
  public class none_enctypeModel : PageModel
  {
    public IFormFile FileData { get; set; }

    public void OnGet()
    {
    }

    public IActionResult OnPost()
    {
      System.IO.Stream stream = FileData.OpenReadStream();
      byte[] buffer = new byte[stream.Length];
      stream.Read(buffer, 0, (int)stream.Length);

      System.IO.FileStream fs = new System.IO.FileStream(FileData.FileName, System.IO.FileMode.CreateNew);
      fs.Write(buffer, 0, buffer.Length);
      fs.Close();
      stream.Close();

      return RedirectToPage("/simple-upload-complete");
    }
  }
}

実行結果

ファイルを選択しPOSTボタンをクリックします。この場合はオブジェクトはnullにならず、ファイルのデータがFileDataプロパティにセットされています。

対処法

動作してしまうため、このままでも問題はありませんが、BindProperty 属性を追加しておくほうが良いかと思われます。
変更前l
  public IFormFile FileData { get; set; }
変更後 (推奨)l
  [BindProperty]
  public IFormFile FileData { get; set; }
著者
iPentecのメインプログラマー
C#, ASP.NET の開発がメイン、少し前まではDelphiを愛用
掲載日: 2020-12-28
iPentec all rights reserverd.