在 Identity GetRolesAsync 中丢失带有异步的 HttpContext ASP.NET 等待
本文关键字:异步 HttpContext ASP 等待 NET GetRolesAsync Identity | 更新日期: 2023-09-27 17:56:29
这更像是一个异步/等待问题,而不是 ASP.NET 身份。我正在使用 Asp.Net Identity,并且有一个自定义的用户存储,带有自定义的GetRolesAsync方法。 用户管理器是从 WebApi 控制器调用的。
public class MyWebApiController {
private MyUserManager manager = new MyUserManager(new MyUserStore());
[HttpGet]
public async Task<bool> MyWebApiMethod(int x) {
IList<string> roles = await manager.GetRolesAsync(x);
return true;
}
}
public class MyUserManager : UserManager<MyUser, int> {
// I do not implement a custom GetRolesAsync in the UserManager, but
// from looking at the identity source, this is what the base class is doing:
// public virtual async Task<IList<string>> GetRolesAsync(TKey userId)
// {
// ThrowIfDisposed();
// var userRoleStore = GetUserRoleStore();
// var user = await FindByIdAsync(userId).WithCurrentCulture();
// if (user == null)
// {
// throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.UserIdNotFound,userId));
// }
// return await userRoleStore.GetRolesAsync(user).WithCurrentCulture();
// }
}
public class MyUserStore {
public async Task<IList<string>> GetRolesAsync(TUser user) {
// I need HttpContext here and it is NULL. WHY??
var currentContext = System.Web.HttpContext.Current; // NULL!
var query = from userRole in _userRoles
where userRole.UserId.Equals(userId)
join role in _roleStore.DbEntitySet on userRole.RoleId equals role.Id
select role.Name;
return await query.ToListAsync();
}
}
为什么 MyUserStore.GetRolesAsync 中的上下文为空?我以为等待传递了上下文?我已经逐步介绍了MyUserStore中的其他异步方法,它们都具有正确的上下文,并且代码似乎几乎相同。
事实证明这是TaskExtensions.WithCurrentCulture
的属性。这些是 EF 的文档,但它们也适用于 ASP.NET 标识:
配置用于等待此任务的等待程序,以避免将延续封送回原始上下文,但保留当前区域性和 UI 区域性。
这会导致同步上下文不封送,从而导致HttpContext
null
。
以下是来源的相关部分:
public void UnsafeOnCompleted(Action continuation)
{
var currentCulture = Thread.CurrentThread.CurrentCulture;
var currentUiCulture = Thread.CurrentThread.CurrentUICulture;
// This part is critical.
_task.ConfigureAwait(false).GetAwaiter().UnsafeOnCompleted(() =>
{
var originalCulture = Thread.CurrentThread.CurrentCulture;
var originalUiCulture = Thread.CurrentThread.CurrentUICulture;
Thread.CurrentThread.CurrentCulture = currentCulture;
Thread.CurrentThread.CurrentUICulture = currentUiCulture;
try
{
continuation();
}
finally
{
Thread.CurrentThread.CurrentCulture = originalCulture;
Thread.CurrentThread.CurrentUICulture = originalUiCulture;
}
});
}