Я использую основную идентификацию asp.net, но намеренно разделил информацию о пользователе в другую таблицу, которая связана через пользовательский класс приложения.
Как я могу получить доступ к этой информации из частичного представления входа в систему?
Другие ответы определяют только то, что нужно извлекать информацию из пользовательского класса приложения. то есть:
var personID = UserManager.GetUserAsync(User).Result.PersonID;
Где мне нужно что-то вроде:
var fullName = UserManager.GetUserAsync(User).Result.Person.FullName;
Я предполагаю, что код не загружает дочернюю таблицу, так как я получаю следующую ошибку в объекте Person:
'Object reference not set to an instance of an object.'
Остальная часть моего кода приведена ниже для справки.
Пользователь приложения:
public class ApplicationUser : IdentityUser
{
[ForeignKey("Person")]
public int PersonID { get; set; }
public virtual Person Person { get; set; }
}
Класс человека
public class Person
{
public int PersonID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
[NotMapped]
[Display(Name = "Full Name")]
public string FullName
{
get { return LastName + ", " + FirstName; }
}
public string Address { get; set; }
public ApplicationUser ApplicationUser { get; set; }
}
Частичный вход:
@using Microsoft.AspNetCore.Identity
@using Models;
@inject SignInManager<ApplicationUser> SignInManager
@inject UserManager<ApplicationUser> UserManager
<ul class="navbar-nav">
@if (SignInManager.IsSignedIn(User))
{
<li class="nav-item">
<a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Manage/Index" title="Manage">Hello @User.Identity?.Name!</a>
@{
var personResult = UserManager.GetUserAsync(User).Result;
var fullName = personResult.Person.FullName;
}
</li>
<li class="nav-item">
<form class="form-inline" asp-area="Identity" asp-page="/Account/Logout" asp-route-returnUrl="@Url.Page("/", new { area = "" })" method="post" >
<button type="submit" class="nav-link btn btn-link text-dark">Logout</button>
</form>
</li>
}
else
{
<li class="nav-item">
<a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Register">Register</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Login">Login</a>
</li>
}
</ul>
@viveknuna 'Object reference not set to an instance of an object.'
На объекте Person. Я предполагаю, что это связано с тем, что таблица лиц не загружается в класс UserManager, и я не знаю, как это решить.
проверьте возвращаемое значение GetUserAsync
@viveknuna Он правильно возвращает пользовательский объект. И я могу получить PersonID, но он не будет детализирован до объекта Person.
у него есть Person как null?
@viveknuna Да Person имеет значение null.
Тогда вам нужно проверить, почему это null
@viveknuna Это вся предпосылка моего вопроса, я подозреваю, что он нулевой, потому что класс UserManager по умолчанию не загружает дочерние таблицы. Так нужно ли его как-то продлевать? Я просто не знаю, как загрузить таблицу лиц.
_userManager.GetUserAsync(User)
основан на EF Core, он не будет загружать связанные данные по умолчанию, вы можете попробовать отложенную загрузку в качестве документа
Я пробовал, как показано ниже в моем случае:
установил пакет:
Модели:
public class ApplicationUser : IdentityUser
{
//you have to set the property virtual here
public virtual Person Person { get; set; }
}
public class Person
{
public int PersonID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
[NotMapped]
[Display(Name = "Full Name")]
public string FullName
{
get { return LastName + ", " + FirstName; }
}
public string Address { get; set; }
//you have to set the property virtual here
public virtual ApplicationUser ApplicationUser { get; set; }
public string ApplicationUserId { get; set; }
}
изменил коды, которые регистрируют dbcontext:
builder.Services.AddDbContext<IdentityLazyloadingContext>(options =>
{
options.UseSqlServer(connectionString);
options.UseLazyLoadingProxies();
});
Результат:
Спасибо за вашу помощь, я думаю, что понимаю нетерпеливую и явную загрузку и как ее использовать в обычном коде. Однако я пытаюсь отобразить имя пользователя из таблицы лиц в стандартном представлении _LoginPartial ядра asp.net, которое является частичным представлением без кода. Смотрите код, который я добавил.
О, моя вина, вы можете попробовать отложенную загрузку, чтобы получить свойства навигации, я обновил свой ответ, пожалуйста, проверьте его.
Ответ от Ruikai Feng отмечен как ответ, так как он поставил меня на правильный путь. Однако в итоге я использовал ленивую загрузку без прокси-фреймворка следующим образом:
public class ApplicationUser : IdentityUser
{
private Person _Person;
public ApplicationUser()
{
}
private ApplicationUser(Action<object, string> lazyLoader)
{
LazyLoader = lazyLoader;
}
private Action<object, string> LazyLoader { get; set; }
[ForeignKey("Person")]
public int PersonID { get; set; }
public Person Person
{
get => LazyLoader.Load(this, ref _Person);
set => _Person = value;
}
}
Расширение:
public static class PocoLoadingExtensions
{
// Load function for Lazy Loading, used in Application User.
public static TRelated Load<TRelated>(
this Action<object, string> loader,
object entity,
ref TRelated navigationField,
[CallerMemberName] string navigationName = null)
where TRelated : class
{
loader?.Invoke(entity, navigationName);
return navigationField;
}
}
в чем проблема с вашим текущим кодом?