ASP.NET CoreでEntity Framework Coreを利用すると InvalidOperationException: Unable to resolve service for type '(プロジェクト名).(DbContext名)' while attempting to activate '(RazorPagesモデル名)'. エラーが発生しページが表示できない現象と対処法を紹介します。
現象
Entity Framework Coreを利用したRazorPagesを作成し、ページにアクセスすると、以下のエラーが発生しページが表示できない状態になります。
エラーメッセージ
InvalidOperationException: Unable to resolve service for type '(プロジェクト名).(DbContext名)' while attempting to activate '(RazorPagesモデル名)'.
エラー例
エラーメッセージ
InvalidOperationException: Unable to resolve service for type 'EntityFrameworkCoreRazorPages.MyDbContext' while attempting to activate 'EntityFrameworkCoreRazorPages.Pages.PageCreateModel'.
原因
RazorPagesのページモデルクラスのコンストラクタで、DbContextのインジェクションが記述されていますが、
プログラムの初期化時にDbContextのインジェクション処理を実行していないため、名前解決ができずエラーが発生します。
private readonly EntityFrameworkCoreRazorPages.MyDbContext _context;
public PageCreateModel(EntityFrameworkCoreRazorPages.MyDbContext context)
{
_context = context;
}
対処法
Program.csファイルでDbContextのインジェクション処理を追加します。
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
var app = builder.Build();
app.UseStaticFiles();
app.UseRouting();
app.MapRazorPages();
app.Run();
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();
修正後のプログラムコード
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();
@page
@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("./Index");
}
}
}
<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>
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("(DB接続文字列)");
}
}
}
実行結果
Program.csを修正するとページが正しく表示される動作になります。
補足:Program.csでDbContextOptionsを設定する場合
Program.csファイルのAddDbContextでオプションを設定する場合は、DbContextクラスのコンストラクタを以下に変更します。
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddDbContext<EntityFrameworkCoreRazorPages.MyDbContext>(
options => options.UseSqlServer("(DB接続文字列)")
);
var app = builder.Build();
app.UseStaticFiles();
app.UseRouting();
app.MapRazorPages();
app.Run();
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
namespace EntityFrameworkCoreRazorPages
{
public class MyDbContext : DbContext
{
public DbSet<MyTable1Rec> MyTable1 { get; set; }
public MyDbContext(DbContextOptions<MyDbContext> options) : base(options)
{
}
}
}
著者
iPentecのメインプログラマー
C#, ASP.NET の開発がメイン、少し前まではDelphiを愛用
最終更新日: 2022-12-18
作成日: 2022-12-17