我在代码中实现了一个自定义 Profile 对象,如 Joel 所述:
但是,当我创建新用户时,我无法让它工作。当我这样做时:
Membership.CreateUser(userName, password);
Roles.AddUserToRole(userName, "MyRole");
用户已创建并添加到数据库中的角色,但HttpContext.Current.User
仍然为空,并Membership.GetUser()
返回 null,因此(来自 Joel 的代码)不起作用:
static public AccountProfile CurrentUser
{
get { return (AccountProfile)
(ProfileBase.Create(Membership.GetUser().UserName)); }
}
AccountProfile.CurrentUser.FullName = "Snoopy";
我尝试过Membership.GetUser(userName)
以这种方式调用和设置 Profile 属性,但设置的属性仍然为空,并且调用AccountProfile.CurrentUser(userName).Save()
不会将任何内容放入数据库中。我还尝试通过调用Membership.ValidateUser
,FormsAuthentication.SetAuthCookie
等指示用户有效并已登录,但当前用户仍然为 null 或匿名(取决于我的浏览器 cookie 的状态)。
已解决(进一步编辑,见下文):根据 Franci Penov 的解释和更多实验,我发现了这个问题。Joel 的代码和我尝试的变体只适用于现有的配置文件。如果 Profile 不存在,ProfileBase.Create(userName)
每次调用都会返回一个新的空对象;您可以设置属性,但它们不会“粘住”,因为每次访问它时都会返回一个新实例。设置HttpContext.Current.User
为 newGenericPrincipal
将为您提供一个 User 对象,但不是Profile 对象,并且ProfileBase.Create(userName)
仍将HttpContext.Current.Profile
指向新的空对象。
如果要在同一请求中为新创建的用户创建 Profile,则需要调用HttpContext.Current.Profile.Initialize(userName, true)
. 然后,您可以填充初始化的配置文件并保存它,它可以在以后的请求中按名称访问,因此 Joel 的代码将起作用。我只在内部使用HttpContext.Current.Profile
,当我需要在创建后立即创建/访问配置文件时。在任何其他请求中,我使用ProfileBase.Create(userName)
,并且我只将该版本公开。
请注意,Franci 是正确的:如果您愿意在第一次往返时创建用户(和角色)并将其设置为已验证,并要求用户然后登录,您将能够更简单地访问配置文件在后续请求中通过 Joel 的代码。让我感到震惊的是,角色可以在用户创建时立即访问,而无需任何初始化,但 Profile 不是。
我的新 AccountProfile 代码:
public static AccountProfile CurrentUser
{
get
{
if (Membership.GetUser() != null)
return ProfileBase.Create(Membership.GetUser().UserName) as AccountProfile;
else
return null;
}
}
internal static AccountProfile NewUser
{
get { return System.Web.HttpContext.Current.Profile as AccountProfile; }
}
新用户创建:
MembershipUser user = Membership.CreateUser(userName, password);
Roles.AddUserToRole(userName, "MyBasicUserRole");
AccountProfile.NewUser.Initialize(userName, true);
AccountProfile.NewUser.FullName = "Snoopy";
AccountProfile.NewUser.Save();
后续访问:
if (Membership.ValidateUser(userName, password))
{
string name = AccountProfile.CurrentUser.FullName;
}
进一步感谢 Franci 解释身份验证生命周期 - 我在我的验证函数中调用 FormsAuthentication.SetAuthCookie ,但我返回一个布尔值表示成功,因为 User.Identity.IsAuthenticated 在后续请求之前不会为真。
修订:我是个白痴。上面的解释适用于狭义的情况,但并没有解决核心问题:调用 CurrentUser 每次都会返回一个对象的新实例,无论它是否是现有的 Profile。因为它被定义为一个属性,所以我没有考虑这个,并写道:
AccountProfile.CurrentUser.FullName = "Snoopy";
AccountProfile.CurrentUser.OtherProperty = "ABC";
AccountProfile.CurrentUser.Save();
这(当然)不起作用。它应该是:
AccountProfile currentProfile = AccountProfile.CurrentUser;
currentProfile.FullName = "Snoopy";
currentProfile.OtherProperty = "ABC";
currentProfile.Save();
完全忽略这个基本点是我自己的错,但我确实认为将 CurrentUser 声明为属性意味着它是一个可以操作的对象。相反,它应该被声明为GetCurrentUser()
.