コードでcshtmlのタグを出力すると、asp-for が無効になる現象を紹介します。
正しく動作する例
コード
下記のRazorPagesを作成します。
@page "/StaticBindTextBox"
@model DynamicGenerateElement.Pages.StaticBindTextBoxModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@{
}
<html>
<head>
</head>
<body>
<h2>テスト動作確認用</h2>
<form method="post">
<input type="text" asp-for="TextBoxString" /><br />
<input type="submit" value="button1" />
</form>
</body>
</html>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace DynamicGenerateElement.Pages
{
public class StaticBindTextBoxModel : PageModel
{
[BindProperty]
public string TextBoxString { get; set; }
public void OnGet()
{
}
public IActionResult OnPost()
{
return RedirectToPage("/StaticBindTextBoxResult", new { text = TextBoxString });
}
}
}
@page "/StaticBindTextBoxResult/{text?}"
@model DynamicGenerateElement.Pages.StaticBindTextBoxResultModel
@{
}
<html>
<head>
</head>
<body>
<h2>テスト動作結果</h2>
<div>Name : @Model.TextString</div>
</body>
</html>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace DynamicGenerateElement.Pages
{
public class StaticBindTextBoxResultModel : PageModel
{
public string TextString;
public void OnGet(string text = "")
{
TextString = text;
}
}
}
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace DynamicGenerateElement
{
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();
});
}
}
}
解説
StaticBindTextBox ページでテキストボックスに文字列を入力し、ボタンをクリックすると、URLのパラメーターにテキストボックスに入力した文字を設定し、StaticBindTextBoxResult ページにリダイレクトします。Razor Pagesでテキストボックスの内容を取得する方法の詳細は
こちらの記事を参照してください。
StaticBindTextBoxResult ページでは、URLのパラメーターの文字列を取得しページ内に表示します。
実行結果
上記のプロジェクトを実行します。
(アプリケーションルート)/StaticBindTextBox
のURLにアクセスします。下図のページが表示されます。
テキストボックスに文字列を入力します。入力後[button1]ボタンをクリックします。
(アプリケーションルート)/StaticBindTextBoxResult/(テキストボックスの値)
のURLにリダイレクトします。ページにテキストボックスに入力した
文字列が表示されます。
現象の確認
以下のRazorPagesを作成します。
コード
@page
@model DynamicGenerateElement.Pages.DynamicGenerateBindTextBoxNC
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@{
}
<html>
<head>
</head>
<body>
<h2>動的出力のデモ</h2>
<form method="post">
@Html.Raw(Model.OutputHTML)
<input type="submit" value="button1" />
</form>
</body>
</html>
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace DynamicGenerateElement.Pages
{
public class DynamicGenerateBindTextBoxNC : PageModel
{
public string OutputHTML { get; set; }
[BindProperty]
public string TextBoxString { get; set; }
public void OnGet()
{
OutputHTML = "<input type=\"text\" asp-for=\"TextBoxString\" /><br />";
}
public IActionResult OnPost()
{
return RedirectToPage("/StaticBindTextBoxResult", new { text = TextBoxString });
}
}
}
解説
Razor Pagesにアクセスしたタイミングで、Razor Pagesのテキストボックスのタグ
<input type="text" asp-for="TextBoxString" /><br />
をページに出力し、動的にページにテキストボックスを生成しています。
実行結果
上記のプロジェクトを実行します。
(アプリケーションルート)/DynamicGenerateBindTextBoxNC
のURLにアクセスします。下図のページが表示されます。
テキストボックスに文字列を入力します。入力後[button1]ボタンをクリックします。
URLはリダイレクトされ、
(アプリケーションルート)/StaticBindTextBoxResult
ページが表示されますが、テキストボックスに入力した文字列はパラメータとして渡されず、ページにもテキストボックスの内容は表示されません。
HTMLの比較
正常に動作した場合と、OnGetでページにタグを出力した場合のHTMLを比較します。
<html>
<head>
</head>
<body>
<h2>テスト動作確認用</h2>
<form method="post">
<input type="text" id="TextBoxString" name="TextBoxString" value="" /><br />
<input type="submit" value="button1" />
<input name="__RequestVerificationToken" type="hidden" value="CfDJ8H4psHKzqwFOtAVrjxx7Q_ysMf8MPORkKqjhb0fXnq6cknVQVliaLdoUa7t_XJWZC-JUDMVyx7Wis-sZurgMXjBMdkE3cxfJ5bhHPsZ929oeuuX8JIue7DtuuIEz1eFpSLy-Zc1aHPHQO02o4qrbVfs" /></form>
</body>
</html>
<html>
<head>
</head>
<body>
<h2>動的出力のデモ</h2>
<form method="post">
<input type="text" asp-for="TextBoxString" /><br />
<input type="submit" value="button1" />
<input name="__RequestVerificationToken" type="hidden" value="CfDJ8H4psHKzqwFOtAVrjxx7Q_xR896YDQF5KiDZ6OZ3ZG-mai_HvF6eH1-GtpZTex12JxpALQMtwUQzoYpxzKzRoCdKj2XqpOpMDVMPQz3vn0o0vXhz6A7gzaZAf0eW7owsqTMNgIV73wsbNTtv_g78uf0" /></form>
</body>
</html>
正しく動作する場合は、hidden フィールドが設定されており、asp-for タグが id, name タグに置き換わっていることが確認できます。
対処法
動的にRazor Pagesのタグを出力する場合は、あらかじめページにタグを記述しておき、
Razor Page側のロジックでタグを書き出さないなどの制御を実装することで、
動的にページの要素の出しわけができます。
例
下記のRazorPagesを作成します。リダイレクト先の
StaticBindTextBoxResult
ページは先のコードのRazorPagesをそのまま利用します。
@page "{param:bool?}"
@model DynamicGenerateElement.Pages.DynamicGenerateBindTextBoxModel
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@{
}
<html>
<head>
</head>
<body>
<h2>動的出力のデモ</h2>
<form method="post">
@if (Model.ShowTextBox == true) {
<input type="text" asp-for="@Model.TextBoxString" /><br />
}
<input type="submit" value="button1" />
</form>
</body>
</html>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace DynamicGenerateElement.Pages
{
public class DynamicGenerateBindTextBoxModel : PageModel
{
public bool ShowTextBox { get; set; }
[BindProperty]
public string TextBoxString { get; set; }
public string target { get; set; }
public void OnGet(bool param)
{
if (param == true) {
ShowTextBox = true;
}
else {
ShowTextBox = false;
}
}
public IActionResult OnPost()
{
return RedirectToPage("/StaticBindTextBoxResult", new { text = TextBoxString });
}
}
}
解説
@page "{param:bool?}"
の記述によりこのRazor Pageでは、boolのパラメーターを受け取る設定とします。
末尾の
?
によりパラメータが記述されていない場合もページの表示をします。
OnGetメソッド内で取得したパラメータの値を確認し、trueであれば、
ShowTextBox
変数の値を
true
に設定します。
public void OnGet(bool param)
{
if (param == true) {
ShowTextBox = true;
}
else {
ShowTextBox = false;
}
}
Razor Pageの下記のコードでモデルクラスのShowTextBox の値を確認し、
true
の場合にif文内を実行し、テキストボックスを画面に表示します。
@if (Model.ShowTextBox == true) {
<input type="text" asp-for="@Model.TextBoxString" /><br />
}
実行結果
上記のプロジェクトを実行し、Webブラウザで
(アプリケーションルート)/DynamicGenerateBindTextBox
のURLにアクセスします。下図のページが表示されます。
パラメーターが無いためテキストボックスが非表示になっています。
URLを
(アプリケーションルート)/DynamicGenerateBindTextBox/true
に変更してアクセスします。下図のページが表示されます。パラメーターにtrueが設定されているため、
テキストボックスがページに表示されます。
URLが
(アプリケーションルート)/DynamicGenerateBindTextBox/false
の場合はテキストボックスは表示されません。
また、URLが
(アプリケーションルート)/DynamicGenerateBindTextBox/(bool値でない文字列)
の場合は、404エラーとなります。
テキストが表示された状態でテキストボックスに文字列を入力し、[button1]をクリックするとリダイレクトが実行され、
StaticBindTextBoxResult
ページが表示され、
テキストボックスに入力した文字列がページに表示されます。
著者
iPentecのメインプログラマー
C#, ASP.NET の開発がメイン、少し前まではDelphiを愛用
最終更新日: 2021-10-28
作成日: 2021-02-13