自定义asp.net身份存储-为什么HttpContext.Current有时为空 [英] custom asp.net identity store - why is HttpContext.Current empty at times
问题描述
通过遵循示例集此处.一切正常,除了:
I've implemented a custom User Store for ASP.NET Identity by following the example set here. That all works fine, except for this:
我需要访问我的用户存储中有关当前登录用户的数据.通常,您可以通过访问
I need access to data about the currently logged in user in my user store. Normally, you'd access that by accessing
HttpContext.Current.User
现在,一旦用户登录,如果该用户随后进入Manage控制器(例如尝试更改其密码),则当ASP.NET身份通过调用再次查找该用户时
Now, once auser has logged in, if he user then goes to the Manage controller (e.g. to try and change his/her password), when ASP.NET identity looks up the user again by calling
CustomUserManager.FindByIdAsync(string userId)
HttpContext.Current完全为空(在呈现页面之前).那么,在这种情况下如何获取有关HttpContext的信息?该用户已正确登录,那么如何确定哪个用户已登录?
HttpContext.Current is empty altogether (that's prior to rendering the page). So, how do I get information about the HttpContext in this scenario? The user is properly logged in, so how do I figure out which user has been logged in?
@edit ..问题出在CustomUserStore ..有点问题
@edit.. the problem is in CustomUserStore.. here's a bit of it
public class CustomUserStore<TUser> : IUserStore<TUser>, IUserLoginStore<TUser>, IUserClaimStore<TUser>, IUserPasswordStore<TUser>, IUserSecurityStampStore<TUser>, IUserEmailStore<TUser>, IUserPhoneNumberStore<TUser>,
IUserLockoutStore<TUser, string>, IUserTwoFactorStore<TUser, string>//, IQueryableUserStore<TUser>
where TUser: CustomUser<string>, IUser<string>
{
string storageFile = @"c:\temp\aspnetusers.json";
List<TUser> users;
public CustomUserStore()
{
if (File.Exists(storageFile))
{
string contents = File.ReadAllText(storageFile);
users = JsonConvert.DeserializeObject<List<TUser>>(contents);
if (users == null)
users = new List<TUser>();
}
else
users = new List<TUser>();
}
#region IUserStore implementation
public Task<TUser> FindByIdAsync(string userId)
{
string sessionId = HttpContext.Current?.Session?.SessionID;
return Task.FromResult<TUser>(users.FirstOrDefault(u => u.Id == userId));
}
public Task<TUser> FindByNameAsync(string userName)
{
string sessionId = HttpContext.Current?.Session?.SessionID;
return Task.FromResult<TUser>(users.FirstOrDefault(u => string.Compare(u.UserName, userName, true) == 0));
}
#endregion
}
,它位于FindByAsync方法中,其中HttpContext.Current可以为空.
and it's in the FindByAsync method where HttpContext.Current can be empty.
创建模型时,它会在AccountController的Index方法中发生
It happens in the Index method of the AccountController when the model is created
var model = new IndexViewModel
{
HasPassword = HasPassword(),
PhoneNumber = await UserManager.GetPhoneNumberAsync(userId),
TwoFactor = await UserManager.GetTwoFactorEnabledAsync(userId),
Logins = await UserManager.GetLoginsAsync(userId),
BrowserRemembered = await AuthenticationManager.TwoFactorBrowserRememberedAsync(userId)
};
导致问题的原因是HasPassword方法中的FindById请求
And it's the FindById request in the HasPassword method that causes the problem
private bool HasPassword()
{
var user = UserManager.FindById(User.Identity.GetUserId());
if (user != null)
{
return user.PasswordHash != null;
}
return false;
}
对用户管理器的其他4个请求均具有填写的HttpContext.Current.因此,似乎是导致问题的原因是对UserManager的调用.
The other 4 requests to the user manager all have a filled out HttpContext.Current. So it appears that it's calls to UserManager that cause the issue.
推荐答案
已经确定了问题的确切根源,因此很容易解决.
Having identified the exact source of the problem, it's easy enough to fix.
添加此异步方法以检查用户是否具有密码:
Add this async emthod to check if the user has a password:
private async Task<bool> HasPasswordAsync()
{
var user = await UserManager.FindByIdAsync(User.Identity.GetUserId());
if (user != null)
{
return user.PasswordHash != null;
}
return false;
}
在Index方法中,使用新的异步方法
And in the Index method, use the new async methode
var model = new IndexViewModel
{
HasPassword = await HasPasswordAsync(),
PhoneNumber = await UserManager.GetPhoneNumberAsync(userId),
TwoFactor = await UserManager.GetTwoFactorEnabledAsync(userId),
Logins = await UserManager.GetLoginsAsync(userId),
BrowserRemembered = await AuthenticationManager.TwoFactorBrowserRememberedAsync(userId)
};
但是,为什么同步方法调用会中断事情呢?您会想象到同步调用将在HttpContext.Current应该可用的标准上下文中运行.
But, why does the synchronous method call break things? You'd imagine the sync call would run into the standard context where HttpContext.Current should be available.
在我的真实项目中,我有一个更自定义的用户存储,在这里我经常遇到此问题..我猜我需要检查是否包含对UserManager方法的更多同步访问.
I have a more custom User Store in my real project where I run into this problem a lot more frequently.. guess I need to check if contains a lot more synchronous access to UserManager methods.
这篇关于自定义asp.net身份存储-为什么HttpContext.Current有时为空的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!