ページ作成ウィザードを利用して、Entity Framework Core を利用したRazor Pageを作成する手順を紹介します。
手順
プロジェクトの作成
今回は空のRazorPagesプロジェクトを作成します。
モデルとDbContextの作成
モデルと、DbContextのコードを作成します。
コードは直接記述しても良いですし、既存のデータベースがある場合は、
Scaffold-DbContext
コマンドを実行して作成しても良いです。
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
namespace EntityFrameworkCoreRazorPages
{
public class MyDbContext : DbContext
{
public DbSet<MyTable1Rec> MyTable1 { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder options)
{
options.UseSqlServer("(データベース接続文字列)");
}
}
}
namespace EntityFrameworkCoreRazorPages
{
public class MyTable1Rec
{
public int id { get; set; }
public string Name { get; set; }
public string Category { get; set; }
public string Code { get; set; }
public int Price { get; set; }
}
}
RazorPageの作成
ソリューションエクスプローラーでプロジェクトに
Pages
フォルダを作成します。フォルダを選択して、右クリックし、[追加]メニューの[Razor ページ...]の項目をクリックします。
下図の[新規スキャフォールディング アイテムの追加]ダイアログが表示されます。[Entity Framework を使用する Razor ページ]の項目を選択し、
ウィンドウ右下の[追加]ボタンをクリックします。
[Entity Framework を使用する Razor ページの追加]ダイアログが表示されます。[テンプレート]のドロップダウンリストボックスをクリックして、テンプレートを選択します。
[Razor ページ名]、[テンプレート]、[モデル クラス]、[データ コンテキスト クラス]を設定します。設定ができたら、[追加]ボタンをクリックします。
スキャフォールディングが実行され、ページが追加されます。
テンプレートを変更して同じ手順を繰り返し、Createテンプレートで"PageCreate"、Deleteテンプレートで"PageDelete"、Detailsテンプレートで"PageDetails"、
Editテンプレートで"PageEdit"、Listテンプレートで"PageList" ページを作成します。
コードの修正
Program.csを変更します。コード内にAddDbContext() メソッドを追加します。
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddDbContext<EntityFrameworkCoreRazorPages.MyDbContext>();
var app = builder.Build();
app.UseStaticFiles();
app.UseRouting();
app.MapRazorPages();
app.Run();
タグヘルパーが利用できるようにするため、各cshtmlファイルの先頭に次のコードを追記します。
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
または、Pages/Shared フォルダ内に _ViewImports.cshtml ファイルを作成し、以下のコードを記述する方法もあります。
@namespace EntityFrameworkCoreRazorPages.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
PageCreate.cshtmlの
asp-page
部分を今回作成したページ名に合わせて修正します。
<a asp-page="./PageList">Back to List</a>
PageCreate.cshtml.cs の
RedirectToPage
メソッドのリダイレクト先パラメーターを今回作成したページ名に合わせて修正します。
return RedirectToPage("./PageList");
PageDelete.cshtmlの
asp-page
部分を今回作成したページ名に合わせて修正します。
<a asp-page="./PageList">Back to List</a>
PageDelete.cshtml.cs の
RedirectToPage
メソッドのリダイレクト先パラメーターを今回作成したページ名に合わせて修正します。
return RedirectToPage("./PageList");
PageDetails.cshtmlの
asp-page
部分を今回作成したページ名に合わせて修正します。
<a asp-page="./PageEdit" asp-route-id="@Model.MyTable1Rec?.id">Edit</a> |
<a asp-page="./PageList">Back to List</a>
PageEdit.cshtmlの
asp-page
部分を今回作成したページ名に合わせて修正します。
<a asp-page="./PageList">Back to List</a>
PageEdit.cshtml.cs の
RedirectToPage
メソッドのリダイレクト先パラメーターを今回作成したページ名に合わせて修正します。
return RedirectToPage("./PageList");
PageList.cshtmlの
asp-page
部分を今回作成したページ名に合わせて修正します。
<a asp-page="PageCreate">Create New</a>
<a asp-page="./PageEdit" asp-route-id="@item.id">Edit</a> |
<a asp-page="./PageDetails" asp-route-id="@item.id">Details</a> |
<a asp-page="./PageDelete" asp-route-id="@item.id">Delete</a>
実行結果
プロジェクトを実行し、
(アプリケーションルートURL)/PageList
のURLにアクセスします。
[Details]のリンクをクリックします。
Details画面が表示されます。
Details画面で[Edit]リンクをクリックするか、List画面で[Edit]リンクをクリックします。下図の編集画面が表示されます。
値を編集し[Save]ボタンをクリックします。
リスト画面に切り替わり、変更内容が反映されていることが確認できます。
コード
コード全体です。
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
namespace EntityFrameworkCoreRazorPages
{
public class MyDbContext : DbContext
{
public DbSet<MyTable1Rec> MyTable1 { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder options)
{
options.UseSqlServer("(データベース接続文字列)");
}
}
}
namespace EntityFrameworkCoreRazorPages
{
public class MyTable1Rec
{
public int id { get; set; }
public string Name { get; set; }
public string Category { get; set; }
public string Code { get; set; }
public int Price { get; set; }
}
}
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddDbContext<EntityFrameworkCoreRazorPages.MyDbContext>();
var app = builder.Build();
app.UseStaticFiles();
app.UseRouting();
app.MapRazorPages();
app.Run();
<environment names="Development">
<script src="~/lib/jquery-validation/dist/jquery.validate.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>
</environment>
<environment names="Staging,Production">
<script src="https://ajax.aspnetcdn.com/ajax/jquery.validate/1.17.0/jquery.validate.min.js"
asp-fallback-src="~/lib/jquery-validation/dist/jquery.validate.min.js"
asp-fallback-test="window.jQuery && window.jQuery.validator"
crossorigin="anonymous"
integrity="sha384-rZfj/ogBloos6wzLGpPkkOr/gpkBNLZ6b6yLy4o+ok+t/SAKlL5mvXLr0OXNi1Hp">
</script>
<script src="https://ajax.aspnetcdn.com/ajax/jquery.validation.unobtrusive/3.2.9/jquery.validate.unobtrusive.min.js"
asp-fallback-src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"
asp-fallback-test="window.jQuery && window.jQuery.validator && window.jQuery.validator.unobtrusive"
crossorigin="anonymous"
integrity="sha384-ifv0TYDWxBHzvAk2Z0n8R434FL1Rlv/Av18DXE43N/1rvHyOG4izKst0f2iSLdds">
</script>
</environment>
@page
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@model EntityFrameworkCoreRazorPages.Pages.PageCreateModel
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>PageCreate</title>
</head>
<body>
<h4>MyTable1Rec</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="MyTable1Rec.Name" class="control-label"></label>
<input asp-for="MyTable1Rec.Name" class="form-control" />
<span asp-validation-for="MyTable1Rec.Name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="MyTable1Rec.Category" class="control-label"></label>
<input asp-for="MyTable1Rec.Category" class="form-control" />
<span asp-validation-for="MyTable1Rec.Category" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="MyTable1Rec.Code" class="control-label"></label>
<input asp-for="MyTable1Rec.Code" class="form-control" />
<span asp-validation-for="MyTable1Rec.Code" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="MyTable1Rec.Price" class="control-label"></label>
<input asp-for="MyTable1Rec.Price" class="form-control" />
<span asp-validation-for="MyTable1Rec.Price" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-page="Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
</body>
</html>
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.Mvc.Rendering;
using EntityFrameworkCoreRazorPages;
namespace EntityFrameworkCoreRazorPages.Pages
{
public class PageCreateModel : PageModel
{
private readonly EntityFrameworkCoreRazorPages.MyDbContext _context;
public PageCreateModel(EntityFrameworkCoreRazorPages.MyDbContext context)
{
_context = context;
}
public IActionResult OnGet()
{
return Page();
}
[BindProperty]
public MyTable1Rec MyTable1Rec { get; set; } = default!;
// To protect from overposting attacks, see https://aka.ms/RazorPagesCRUD
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid || _context.MyTable1 == null || MyTable1Rec == null)
{
return Page();
}
_context.MyTable1.Add(MyTable1Rec);
await _context.SaveChangesAsync();
return RedirectToPage("./PageList");
}
}
}
@page
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@model EntityFrameworkCoreRazorPages.Pages.PageDeleteModel
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>PageDelete</title>
</head>
<body>
<h3>Are you sure you want to delete this?</h3>
<div>
<h4>MyTable1Rec</h4>
<hr />
<dl class="row">
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.MyTable1Rec.Name)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.MyTable1Rec.Name)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.MyTable1Rec.Category)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.MyTable1Rec.Category)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.MyTable1Rec.Code)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.MyTable1Rec.Code)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.MyTable1Rec.Price)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.MyTable1Rec.Price)
</dd>
</dl>
<form method="post">
<input type="hidden" asp-for="MyTable1Rec.id" />
<input type="submit" value="Delete" class="btn btn-danger" /> |
<a asp-page="./PageList">Back to List</a>
</form>
</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;
using Microsoft.EntityFrameworkCore;
using EntityFrameworkCoreRazorPages;
namespace EntityFrameworkCoreRazorPages.Pages
{
public class PageDeleteModel : PageModel
{
private readonly EntityFrameworkCoreRazorPages.MyDbContext _context;
public PageDeleteModel(EntityFrameworkCoreRazorPages.MyDbContext context)
{
_context = context;
}
[BindProperty]
public MyTable1Rec MyTable1Rec { get; set; } = default!;
public async Task<IActionResult> OnGetAsync(int? id)
{
if (id == null || _context.MyTable1 == null)
{
return NotFound();
}
var mytable1rec = await _context.MyTable1.FirstOrDefaultAsync(m => m.id == id);
if (mytable1rec == null)
{
return NotFound();
}
else
{
MyTable1Rec = mytable1rec;
}
return Page();
}
public async Task<IActionResult> OnPostAsync(int? id)
{
if (id == null || _context.MyTable1 == null)
{
return NotFound();
}
var mytable1rec = await _context.MyTable1.FindAsync(id);
if (mytable1rec != null)
{
MyTable1Rec = mytable1rec;
_context.MyTable1.Remove(MyTable1Rec);
await _context.SaveChangesAsync();
}
return RedirectToPage("./PageList");
}
}
}
@page
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@model EntityFrameworkCoreRazorPages.Pages.PageDetailsModel
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>PageDetails</title>
</head>
<body>
<div>
<h4>MyTable1Rec</h4>
<hr />
<dl class="row">
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.MyTable1Rec.Name)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.MyTable1Rec.Name)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.MyTable1Rec.Category)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.MyTable1Rec.Category)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.MyTable1Rec.Code)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.MyTable1Rec.Code)
</dd>
<dt class="col-sm-2">
@Html.DisplayNameFor(model => model.MyTable1Rec.Price)
</dt>
<dd class="col-sm-10">
@Html.DisplayFor(model => model.MyTable1Rec.Price)
</dd>
</dl>
</div>
<div>
<a asp-page="./Edit" asp-route-id="@Model.MyTable1Rec?.id">Edit</a> |
<a asp-page="./Index">Back to List</a>
</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;
using Microsoft.EntityFrameworkCore;
using EntityFrameworkCoreRazorPages;
namespace EntityFrameworkCoreRazorPages.Pages
{
public class PageDetailsModel : PageModel
{
private readonly EntityFrameworkCoreRazorPages.MyDbContext _context;
public PageDetailsModel(EntityFrameworkCoreRazorPages.MyDbContext context)
{
_context = context;
}
public MyTable1Rec MyTable1Rec { get; set; } = default!;
public async Task<IActionResult> OnGetAsync(int? id)
{
if (id == null || _context.MyTable1 == null)
{
return NotFound();
}
var mytable1rec = await _context.MyTable1.FirstOrDefaultAsync(m => m.id == id);
if (mytable1rec == null)
{
return NotFound();
}
else
{
MyTable1Rec = mytable1rec;
}
return Page();
}
}
}
@page
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@model EntityFrameworkCoreRazorPages.Pages.PageEditModel
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>PageEdit</title>
</head>
<body>
<h4>MyTable1Rec</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="MyTable1Rec.id" />
<div class="form-group">
<label asp-for="MyTable1Rec.Name" class="control-label"></label>
<input asp-for="MyTable1Rec.Name" class="form-control" />
<span asp-validation-for="MyTable1Rec.Name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="MyTable1Rec.Category" class="control-label"></label>
<input asp-for="MyTable1Rec.Category" class="form-control" />
<span asp-validation-for="MyTable1Rec.Category" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="MyTable1Rec.Code" class="control-label"></label>
<input asp-for="MyTable1Rec.Code" class="form-control" />
<span asp-validation-for="MyTable1Rec.Code" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="MyTable1Rec.Price" class="control-label"></label>
<input asp-for="MyTable1Rec.Price" class="form-control" />
<span asp-validation-for="MyTable1Rec.Price" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-page="./PageList">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
</body>
</html>
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.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using EntityFrameworkCoreRazorPages;
namespace EntityFrameworkCoreRazorPages.Pages
{
public class PageEditModel : PageModel
{
private readonly EntityFrameworkCoreRazorPages.MyDbContext _context;
public PageEditModel(EntityFrameworkCoreRazorPages.MyDbContext context)
{
_context = context;
}
[BindProperty]
public MyTable1Rec MyTable1Rec { get; set; } = default!;
public async Task<IActionResult> OnGetAsync(int? id)
{
if (id == null || _context.MyTable1 == null)
{
return NotFound();
}
var mytable1rec = await _context.MyTable1.FirstOrDefaultAsync(m => m.id == id);
if (mytable1rec == null)
{
return NotFound();
}
MyTable1Rec = mytable1rec;
return Page();
}
// To protect from overposting attacks, enable the specific properties you want to bind to.
// For more details, see https://aka.ms/RazorPagesCRUD.
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Attach(MyTable1Rec).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!MyTable1RecExists(MyTable1Rec.id))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToPage("./PageList");
}
private bool MyTable1RecExists(int id)
{
return (_context.MyTable1?.Any(e => e.id == id)).GetValueOrDefault();
}
}
}
@page
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@model EntityFrameworkCoreRazorPages.Pages.PageListModel
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>PageList</title>
</head>
<body>
<p>
<a asp-page="PageCreate">Create New</a>
</p>
<table class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.MyTable1Rec[0].Name)
</th>
<th>
@Html.DisplayNameFor(model => model.MyTable1Rec[0].Category)
</th>
<th>
@Html.DisplayNameFor(model => model.MyTable1Rec[0].Code)
</th>
<th>
@Html.DisplayNameFor(model => model.MyTable1Rec[0].Price)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.MyTable1Rec) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Name)
</td>
<td>
@Html.DisplayFor(modelItem => item.Category)
</td>
<td>
@Html.DisplayFor(modelItem => item.Code)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
<a asp-page="./PageEdit" asp-route-id="@item.id">Edit</a> |
<a asp-page="./PageDetails" asp-route-id="@item.id">Details</a> |
<a asp-page="./PageDelete" asp-route-id="@item.id">Delete</a>
</td>
</tr>
}
</tbody>
</table>
</body>
</html>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using EntityFrameworkCoreRazorPages;
namespace EntityFrameworkCoreRazorPages.Pages
{
public class PageListModel : PageModel
{
private readonly EntityFrameworkCoreRazorPages.MyDbContext _context;
public PageListModel(EntityFrameworkCoreRazorPages.MyDbContext context)
{
_context = context;
}
public IList<MyTable1Rec> MyTable1Rec { get;set; } = default!;
public async Task OnGetAsync()
{
if (_context.MyTable1 != null)
{
MyTable1Rec = await _context.MyTable1.ToListAsync();
}
}
}
}
著者
iPentecのメインプログラマー
C#, ASP.NET の開発がメイン、少し前まではDelphiを愛用
最終更新日: 2023-03-22
作成日: 2022-12-18