ASP.NET 尝试激活控制器时无法解析服务类型
ASP.NET Unable to resolve service for type, while attempting to activate controller
虽然我知道关于这个主题还有其他问题,但我很难理解答案,希望有人能告诉我 DbContext 的工作原理,因为我觉得我可能在不应该创建第二个上下文的时候创建了第二个上下文'没有。
所以,当我自学更多关于 .NET Core 的知识时,我正在努力将一个老式学校项目转变为一个 .NET 项目,这是一个简单的牙医办公室 Web 应用程序,用户可以在其中注册预约,查看他们的约会等。我和 this tutorial 一起添加了额外的用户属性,而不仅仅是用户名和电子邮件,因为我在创建约会时试图抓住当前用户。
在我使用默认的 IdentityUI 添加此自定义属性之前,我让我的项目在用户可以注册和登录的地方工作,创建一个基本约会,他们 'username' 选择一个日期和时间,一旦创建就会显示他们的基本 table 格式的约会。我的下一步是添加自定义用户属性,这样它就会根据他们的真实姓名而不是他们的用户名显示,后者默认为他们的电子邮件。
按照教程,我不确定我是否误解了,但我创建了一个新的 Context 和 IdentityUser,它们都有效,但它破坏了我的 'Appointments' 页面,给我:
InvalidOperationException: Unable to resolve service for type 'Microsoft.AspNetCore.Identity.UserManager`1[Microsoft.AspNetCore.Identity.IdentityUser]' while attempting to activate 'WelchDentistry.Controllers.AppointmentsController'.** error.
这是我的 ConfigureServices 方法,因为我认为这是关于注册 2 个不同上下文的问题。
public void ConfigureServices(IServiceCollection services)
{
/*
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
*/
/*
services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
*/
services.AddControllersWithViews();
services.AddRazorPages();
services.AddMvc();
}
这里是原文上下文
namespace WelchDentistry.Data
{
public class ApplicationDbContext : IdentityDbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
public DbSet<WelchDentistry.Models.Appointment> Appointment { get; set; }
}
}
这是我的约会控制器
namespace WelchDentistry.Controllers
{
public class AppointmentsController : Controller
{
private readonly ApplicationDbContext _context;
private readonly UserManager<IdentityUser> _userManager;
public AppointmentsController(ApplicationDbContext context, UserManager<IdentityUser> userManager)
{
_context = context;
_userManager = userManager;
}
// GET: Appointments
public async Task<IActionResult> Index()
{
var user = await _userManager.GetUserAsync(HttpContext.User);
return View(await _context.Appointment.ToListAsync());
}
// GET: Appointments/Details/5
public async Task<IActionResult> Details(int? id)
{
if (id == null)
{
return NotFound();
}
var appointment = await _context.Appointment
.FirstOrDefaultAsync(m => m.ID == id);
if (appointment == null)
{
return NotFound();
}
return View(appointment);
}
// GET: Appointments/Create
public IActionResult Create()
{
return View();
}
// POST: Appointments/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("ID, CustomerName, AppointmentTime,CustomerDoctor")] Appointment appointment)
{
if (ModelState.IsValid)
{
_context.Add(appointment);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(appointment);
}
// GET: Appointments/Edit/5
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var appointment = await _context.Appointment.FindAsync(id);
if (appointment == null)
{
return NotFound();
}
return View(appointment);
}
// POST: Appointments/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("ID,CustomerName,AppointmentTime,CustomerDoctor")] Appointment appointment)
{
if (id != appointment.ID)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(appointment);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!AppointmentExists(appointment.ID))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
return View(appointment);
}
// GET: Appointments/Delete/5
public async Task<IActionResult> Delete(int? id)
{
if (id == null)
{
return NotFound();
}
var appointment = await _context.Appointment
.FirstOrDefaultAsync(m => m.ID == id);
if (appointment == null)
{
return NotFound();
}
return View(appointment);
}
// POST: Appointments/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{
var appointment = await _context.Appointment.FindAsync(id);
_context.Appointment.Remove(appointment);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
private bool AppointmentExists(int id)
{
return _context.Appointment.Any(e => e.ID == id);
}
}
}
如果需要更多代码,请询问,或者您可以在 my Github
上查看
我感谢所有的帮助和帮助,因为我仍然对其中的大部分内容感到困惑,但正在慢慢学习。
首先删除您身份区域中的 IdentityHostingStartup 文件。
然后将您的数据库上下文更改为此(您应该介绍您的用户 class):
public class ApplicationDbContext : IdentityDbContext<WelchDentistryUser, IdentityRole, string>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
public DbSet<Models.Appointment> Appointment { get; set; }
}
并将此代码添加到您的启动文件中。
services.AddIdentity<WelchDentistryUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
最后,您应该在控制器中使用您的自定义用户 class。
public class AppointmentsController : Controller
{
private readonly ApplicationDbContext _context;
private readonly UserManager<WelchDentistryUser> _userManager;
public AppointmentsController(ApplicationDbContext context, UserManager<WelchDentistryUser> userManager)
{
_context = context;
_userManager = userManager;
}
}
虽然我知道关于这个主题还有其他问题,但我很难理解答案,希望有人能告诉我 DbContext 的工作原理,因为我觉得我可能在不应该创建第二个上下文的时候创建了第二个上下文'没有。
所以,当我自学更多关于 .NET Core 的知识时,我正在努力将一个老式学校项目转变为一个 .NET 项目,这是一个简单的牙医办公室 Web 应用程序,用户可以在其中注册预约,查看他们的约会等。我和 this tutorial 一起添加了额外的用户属性,而不仅仅是用户名和电子邮件,因为我在创建约会时试图抓住当前用户。
在我使用默认的 IdentityUI 添加此自定义属性之前,我让我的项目在用户可以注册和登录的地方工作,创建一个基本约会,他们 'username' 选择一个日期和时间,一旦创建就会显示他们的基本 table 格式的约会。我的下一步是添加自定义用户属性,这样它就会根据他们的真实姓名而不是他们的用户名显示,后者默认为他们的电子邮件。
按照教程,我不确定我是否误解了,但我创建了一个新的 Context 和 IdentityUser,它们都有效,但它破坏了我的 'Appointments' 页面,给我:
InvalidOperationException: Unable to resolve service for type 'Microsoft.AspNetCore.Identity.UserManager`1[Microsoft.AspNetCore.Identity.IdentityUser]' while attempting to activate 'WelchDentistry.Controllers.AppointmentsController'.** error.
这是我的 ConfigureServices 方法,因为我认为这是关于注册 2 个不同上下文的问题。
public void ConfigureServices(IServiceCollection services)
{
/*
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
*/
/*
services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
*/
services.AddControllersWithViews();
services.AddRazorPages();
services.AddMvc();
}
这里是原文上下文
namespace WelchDentistry.Data { public class ApplicationDbContext : IdentityDbContext { public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) { } public DbSet<WelchDentistry.Models.Appointment> Appointment { get; set; } } }
这是我的约会控制器
namespace WelchDentistry.Controllers
{
public class AppointmentsController : Controller
{
private readonly ApplicationDbContext _context;
private readonly UserManager<IdentityUser> _userManager;
public AppointmentsController(ApplicationDbContext context, UserManager<IdentityUser> userManager)
{
_context = context;
_userManager = userManager;
}
// GET: Appointments
public async Task<IActionResult> Index()
{
var user = await _userManager.GetUserAsync(HttpContext.User);
return View(await _context.Appointment.ToListAsync());
}
// GET: Appointments/Details/5
public async Task<IActionResult> Details(int? id)
{
if (id == null)
{
return NotFound();
}
var appointment = await _context.Appointment
.FirstOrDefaultAsync(m => m.ID == id);
if (appointment == null)
{
return NotFound();
}
return View(appointment);
}
// GET: Appointments/Create
public IActionResult Create()
{
return View();
}
// POST: Appointments/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("ID, CustomerName, AppointmentTime,CustomerDoctor")] Appointment appointment)
{
if (ModelState.IsValid)
{
_context.Add(appointment);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(appointment);
}
// GET: Appointments/Edit/5
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var appointment = await _context.Appointment.FindAsync(id);
if (appointment == null)
{
return NotFound();
}
return View(appointment);
}
// POST: Appointments/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("ID,CustomerName,AppointmentTime,CustomerDoctor")] Appointment appointment)
{
if (id != appointment.ID)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(appointment);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!AppointmentExists(appointment.ID))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
return View(appointment);
}
// GET: Appointments/Delete/5
public async Task<IActionResult> Delete(int? id)
{
if (id == null)
{
return NotFound();
}
var appointment = await _context.Appointment
.FirstOrDefaultAsync(m => m.ID == id);
if (appointment == null)
{
return NotFound();
}
return View(appointment);
}
// POST: Appointments/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{
var appointment = await _context.Appointment.FindAsync(id);
_context.Appointment.Remove(appointment);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
private bool AppointmentExists(int id)
{
return _context.Appointment.Any(e => e.ID == id);
}
}
}
如果需要更多代码,请询问,或者您可以在 my Github
上查看我感谢所有的帮助和帮助,因为我仍然对其中的大部分内容感到困惑,但正在慢慢学习。
首先删除您身份区域中的 IdentityHostingStartup 文件。
然后将您的数据库上下文更改为此(您应该介绍您的用户 class):
public class ApplicationDbContext : IdentityDbContext<WelchDentistryUser, IdentityRole, string>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
public DbSet<Models.Appointment> Appointment { get; set; }
}
并将此代码添加到您的启动文件中。
services.AddIdentity<WelchDentistryUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
最后,您应该在控制器中使用您的自定义用户 class。
public class AppointmentsController : Controller
{
private readonly ApplicationDbContext _context;
private readonly UserManager<WelchDentistryUser> _userManager;
public AppointmentsController(ApplicationDbContext context, UserManager<WelchDentistryUser> userManager)
{
_context = context;
_userManager = userManager;
}
}