Razor Pages の RedirectToPage メソッドのリダイレクトで InvalidOperationException : No page named ... matches the supplied values. 例外が発生する - ASP.NET Core

Razor Pages の RedirectToPage メソッドのリダイレクトで InvalidOperationException : No page named ... matches the supplied values. 例外が発生する現象について紹介します。

現象の確認

ASP.NET Core Webアプリケーションを作成し、以下の2つのRazor Pages 作成します。
/Pages/demo-pagename/main.cshtml
@page
@model RedirectPage.Pages.wrong_demo.IndexModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@{
}
<html>
<head>

</head>
<body>
  <p>リダイレクトのテストページ</p>
  <form method="post">
    <input type="submit" value="POST"/>
  </form>
</body>
</html>
/Pages/demo-pagename/main.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 RedirectPage.Pages.wrong_demo
{
  public class IndexModel : PageModel
  {
    public void OnGet()
    {
    }
    public IActionResult OnPost()
    {
      return RedirectToPage("/results/destination");
    }
  }
}
/Pages/demo-pagename/dest.cshtml
@page "/results/destination"
@{
}
<html>
<head></head>
<body>
  <p>リダイレクト先のページです。</p>
</body>
</html>
startup.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace RedirectPage
{
  public class Startup
  {
    // This method gets called by the runtime. Use this method to add services to the container.
    // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
    public void ConfigureServices(IServiceCollection services)
    {
      services.AddRazorPages();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
      if (env.IsDevelopment()) {
        app.UseDeveloperExceptionPage();
      }
      app.UseRouting();
      app.UseEndpoints(endpoints =>
      {
        endpoints.MapRazorPages();
      });
    }
  }
}

解説

/Pages/demo-pagename/main.cshtml ではフォーム内にサブミットボタンを配置しています。クリックによりフォームのポストが実行され、 /Pages/demo-pagename/main.cshtml.cs 内の OnPost メソッドが呼び出され、RedirectToPage() メソッドの呼び出しでページのリダイレクトが実行されます。

/Pages/demo-pagename/dest.cshtml がリダイレクト先です。
@page "/results/destination" が指定されているため、このページのURLは (アプリケーションルート)/resutls/destination のURLになります。

動作確認

アプリケーションの動作を確認します。
最初に (アプリケーションルート)/demo-pagename/main を開きます。ページが表示され、サブミットボタンが表示されています。


次に (アプリケーションルート)/demo-pagename/dest を開きます。こちらのページは page ディレクティブで別の名称が設定されているため表示できません。
ページが見つからない旨のエラーメッセージが表示されます。


続いて、page ディレクティブで指定したURL (アプリケーションルート)/results/destination を開きます。ページが表示されることが確認できました。


(アプリケーションルート)/demo-pagename/main に戻りフォーム内のサブミットボタン([]ボタン)をクリックします。


クリックすると、下図の例外画面が表示されます。


以下のメッセージが表示されます。
エラーメッセージ
An unhandled exception occurred while processing the request.
InvalidOperationException: No page named '/results/destination' matches the supplied values.

原因

RedirectToPage メソッドの第一引数 pageName にはページのリダイレクトURLではなくページのファイル名を指定する必要があります。
今回の例では、Razor Pageのファイルは /Pages/demo-pagename/dest.cshtml に配置されているファイルのため、"/demo-pagename/dest" を与える必要があります。

修正

/Pages/demo-pagename/main.cshtml.cs ファイルのコードのRedirectToPageメソッドの引数の値を変更します。
/Pages/demo-pagename/main.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 RedirectPage.Pages.wrong_demo
{
  public class IndexModel : PageModel
  {
    public void OnGet()
    {
    }
    public IActionResult OnPost()
    {
      return RedirectToPage("/demo-pagename/dest");
    }
  }
}

実行結果

コード変更後プロジェクトを実行し、(アプリケーションルート)/demo-pagename/main を開きます。ページが表示され、サブミットボタンが表示されます。
[POST]ボタンをクリックします。


ボタンをクリックすると、リダイレクト先のページが表示されます。RedirectToPage() メソッドにはページの名前である "/demo-pagename/dest" を与えていますが、 リダイレクト先のURLは(アプリケーションルート)/results/destination になっており、dest.cshtml に設定した @page ディレクティブで指定したURLに 正しくリダイレクトされます。


別の修正方法

リダイレクト先をページの名前ではなくURLで設定したい場合は、RedirectToPage メソッドではなく、Redirect メソッドを利用します。

/Pages/demo-pagename/main.cshtml.cs ファイルのコードを下記に変更します。
/Pages/demo-pagename/main.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 RedirectPage.Pages.wrong_demo
{
  public class IndexModel : PageModel
  {
    public void OnGet()
    {
    }
    public IActionResult OnPost()
    {
      return Redirect("/results/destination");
    }
  }
}

実行結果

上記のコードに変更後プロジェクトを実行します。
(アプリケーションルート)/demo-pagename/main を開きます。ページが表示され、サブミットボタンが表示されます。


ボタンをクリックすると、リダイレクト先のページが表示されます。Redirect メソッドに設定したURLにリダイレクトされることが確認できます。

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