---
lang: ja-jp
breaks: true
---
# ASP.NET Core `AddDefaultIdentity` を使用したアカウントの確認時に「No page named '/Index' matches the supplied values.」が発生する 2023-06-23

```shell=
An unhandled exception occurred while processing the request.
InvalidOperationException: No page named '/Index' matches the supplied values.
Microsoft.AspNetCore.Mvc.Infrastructure.RedirectToPageResultExecutor.ExecuteAsync(ActionContext context, RedirectToPageResult result)
```
```shell=
InvalidOperationException: No page named '/Index' matches the supplied values.
Microsoft.AspNetCore.Mvc.Infrastructure.RedirectToPageResultExecutor.ExecuteAsync(ActionContext context, RedirectToPageResult result)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext<TFilter, TFilterAsync>(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeNextResultFilterAsync<TFilter, TFilterAsync>()
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext<TFilter, TFilterAsync>(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters()
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)
```
```shell=
Show raw exception details
System.InvalidOperationException: No page named '/Index' matches the supplied values.
at Microsoft.AspNetCore.Mvc.Infrastructure.RedirectToPageResultExecutor.ExecuteAsync(ActionContext context, RedirectToPageResult result)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext[TFilter,TFilterAsync](State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeNextResultFilterAsync[TFilter,TFilterAsync]()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext[TFilter,TFilterAsync](State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)
```
## 発生環境
* Visual Studio 2022
* Blazor Server
* スキャフォールディングは一切行っていない状態
* メール送信にSendGridを使用
## 発生状況
メール確認の本文にあるリンクをクリックすると発生する。

## 参考資料
> RegisterConfirmation failing
> https://learn.microsoft.com/en-us/answers/questions/1254239/registerconfirmation-failing
## 調査
### `ConfirmEmail`をスキャフォールディングし、デバッグ実行

`userID`には値が入っているが、`code`が`null`となっていることで発生していた。

### `Confirm your email`の本文にある`a`タグのURL中の`&`がエンコードされて`&`となっていることで`code`が取得出来なかった模様
```
Please confirm your account by <a href='https://localhost:7199/Identity/Account/ConfirmEmail?userId=1f19a918-5154-49ce-aaf7-0721b2ef0564&code=Q2ZESjhLek1mczlxcDROS253Z2U4K05QS1NZbWRsY0N1SytNUTFIQ01QU24veWJNSHE1THg4SlVodzZibWlRbXNCMUlhamFBUGc0dFUvZWNTcDdNSTF6dlplYTMzUW9TZWRJUm5PclJsWi9wam13UWhaM3dXRzA2UVRXb0owUllTSDNDRFZndkFzU2M0MVpLdG5GRkdGMlBhZXpUUm0wcDBpUEZLa2U0dUJGTU10Yy9vbDQvS0QrbmpVVFBLcFgyVVVCUi9nbGNkNUtKQzd0U1hYRS9LckhJNkVab3VMMXJtbXZuMkxLS054VEpPOWxMR05HeXN6ejdkaEtrNTZkMWFQb0xXQT09&returnUrl=%2F'>clicking here</a>.
```
トラブルの元となる為、HTMLメールは送信しないほうがよさそう。。。スマホからだとHTMLメールの方が便利か。。。
### 該当のソースコード
> src/Identity/UI/src/Areas/Identity/Pages/V5/Account/Register.cshtml.cs
> https://github.com/dotnet/aspnetcore/blob/da8a6f0766d1f333cc2faec72f97751e3c605dac/src/Identity/UI/src/Areas/Identity/Pages/V5/Account/Register.cshtml.cs#L149C20-L149C20
:::info
`HtmlEncoder.Default.Encode`されている。
:::

### 一時しのぎの対応
メール送信部分で、メール本文をHTMLデコードすることでとりあえずは動作する。
```csharp=
public class EmailSender : IEmailSender
{
private readonly ILogger _logger;
public EmailSender(IOptions<AuthMessageSenderOptions> optionsAccessor,
ILogger<EmailSender> logger)
{
Options = optionsAccessor.Value;
_logger = logger;
}
public AuthMessageSenderOptions Options { get; } //Set with Secret Manager.
public async Task SendEmailAsync(
string toEmail,
string subject,
string message
)
{
if (string.IsNullOrEmpty(Options.SendGridKey))
{
throw new Exception("Null SendGridKey");
}
await Execute(Options.SendGridKey, subject, message, toEmail);
}
public async Task Execute(
string apiKey,
string subject,
string message,
string toEmail
)
{
var client = new SendGridClient(apiKey);
var from = new EmailAddress(
Options.FromEmail,
Options.FromEmailName
);
var to = new EmailAddress(toEmail, "");
// 確認用のURLに `&` が含まれるのでデコードする。
var plainTextContent = HttpUtility.HtmlDecode(message);
_logger.LogInformation($"[{subject}]");
_logger.LogInformation($"[{plainTextContent}]");
// HTMLメールはそのまま
string htmlContent = message;
SendGridMessage msg = MailHelper.CreateSingleEmail(
from,
to,
subject,
plainTextContent,
htmlContent
);
// Disable click tracking.
// See https://sendgrid.com/docs/User_Guide/Settings/tracking.html
msg.SetClickTracking(false, false);
var response = await client.SendEmailAsync(msg);
_logger.LogInformation(response.IsSuccessStatusCode
? $"Email to {toEmail} queued successfully!"
: $"Failure Email to {toEmail}");
}
}
```