我已向标准项目的 ApplicationUser 添加了一些特定属性。 一些添加的属性属于自定义类。 由于我使用 EntityFramework,它为用户创建一个 dbtable,并为每个自定义类创建一个 dbtable。 我将属性添加到我的 ManageController 和 View 中,并将这些属性添加到特定的 dbtable 中,但我无法访问它们。在 dbo.AspNetUsers 中添加了一列,在属性 + ID 之后调用(在我的示例中为“NameID”)。
现在,如果我在 ManageController 中加载用户,则会加载每个普通属性,但自定义属性为空。
我的问题是,如何加载自定义对象(实际上存储在另一个表中)。
ApplicationUser.cs:
namespace refProject.Models
{
public class ApplicationUser : IdentityUser
{
public Name Name { get; set; }
}
}
管理 Controller .cs
//other usings
using refProject.Models;
using refProject.Models.ManageViewModels;
namespace refProject.Controllers
{
[Authorize]
public class ManageController : Controller
{
private readonly UserManager<ApplicationUser> _userManager;
//other managers
public ManageController(
UserManager<ApplicationUser> userManager,
//other managers
)
{
_userManager = userManager;
//other managers
}
//
// GET: /Manage/Index
[HttpGet]
public async Task<IActionResult> Index(ManageMessageId? message = null)
{
ViewData["StatusMessage"] =
message == ManageMessageId.ChangeNameSuccess ? "Your name has been changed."
: message == ManageMessageId.SetNameSuccess ? "Your name has been set."
: "";
var user = await GetCurrentUserAsync();
if (user == null)
{
return View("Error");
}
var model = new IndexViewModel
{
//other Properties
//
//
// THIS ONE IS NULL
//
//
Name = user.Name
//other Properties
};
return View(model);
}
// GET: /Manage/ChangeName
[HttpGet]
public IActionResult ChangeName()
{
return View();
}
//
// POST: /Manage/ChangeName
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> ChangeName(ChangeNameViewModel model)
{
if(!ModelState.IsValid)
{
return View(model);
}
var user = await GetCurrentUserAsync();
if(user != null)
{
Name NewName = new Name();
NewName.FirstName = model.NewFirstName;
NewName.LastName = model.NewLastName;
user.Name = NewName;
IdentityResult result = await _userManager.UpdateAsync(user);
if (result.Succeeded)
{
return RedirectToAction(nameof(Index), new { Message = ManageMessageId.ChangeNameSuccess });
}
AddErrors(result);
return View(model);
}
return RedirectToAction(nameof(Index), new { Message = ManageMessageId.Error });
}
//
// GET: /Manage/SetName
[HttpGet]
public IActionResult SetName()
{
return View();
}
//
// POST: /Manage/SetName
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> SetName(SetNameViewModel model)
{
if(!ModelState.IsValid)
{
return View(model);
}
var user = await GetCurrentUserAsync();
if(user != null)
{
Name NewName = new Name();
NewName.FirstName = model.NewFirstName;
NewName.LastName = model.NewLastName;
user.Name = NewName;
IdentityResult result = await _userManager.UpdateAsync(user);
if(result.Succeeded)
{
return RedirectToAction(nameof(Index), new { Message = ManageMessageId.SetNameSuccess });
}
AddErrors(result);
return View(model);
}
return RedirectToAction(nameof(Index), new { Message = ManageMessageId.Error });
}
#region Helpers
private void AddErrors(IdentityResult result)
{
foreach (var error in result.Errors)
{
ModelState.AddModelError(string.Empty, error.Description);
}
}
public enum ManageMessageId
{
Error,
ChangeNameSuccess,
SetNameSuccess,
}
private Task<ApplicationUser> GetCurrentUserAsync()
{
return _userManager.GetUserAsync(HttpContext.User);
}
#endregion
}
}
名称.cs
namespace refProject.Models
{
public class Name
{
public int ID { get; set; }
public string fTitle { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string lTitle { get; set; }
public override string ToString()
{
return fTitle + " " + FirstName + " " + LastName + " " + lTitle;
}
}
}
最佳答案
这是一个已知问题。它不被视为错误,而是设计决策。
推荐的方法是通过 DbContext
而不是通过 UserManager
实现来访问用户。
"Just to add a bit more detail: as a performance optimization ASP.NET Core Identity currently only loads the entities related to a user or a role as needed to satisfy API calls. I.e. it won't load related entities (not even the built-in ones) eagerly on a method call like such as
FindByName()
because the find methods are only required to return the root.At this point issuing queries against the
DbContext
is the recommended way to load related data. If you want to abstract this from the application code you can extend both the Identity store and manager classes to add methods to retrieve and return your custom related data."
您可以按如下方式更改 GetCurrentUserAsync
方法:
private ApplicationUser GetCurrentUserAsync()
{
return _userManager.Users.Include(x => x.Name).FirstOrDefault(x => x.Id == _userManager.GetUserId(User));
}
关于c# - .Net Core获取ApplicationUser的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44833245/