我在代码中实现了一个自定义配置文件对象,正如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)
并以这种方式设置配置文件属性,但是设置的属性仍然是空的,并且调用AccountProfile.CurrentUser(userName).Save()
不会在数据库中放入任何内容。我还尝试通过调用Membership.ValidateUser
、FormsAuthentication.SetAuthCookie
等来指示用户是有效的&已登录,但当前用户仍然是空的或匿名的(取决于浏览器cookie的状态)。
解决了(进一步编辑,见下文):基于Franci Penov的解释和一些更多的实验,我弄清楚了这个问题。Joel的代码和我尝试的变体只适用于现有的配置文件。如果不存在配置文件,ProfileBase.Create(userName)
将在每次调用它时返回一个新的空对象;您可以设置属性,但它们不会“粘滞”,因为每次访问它时都会返回一个新的实例。将HttpContext.Current.User
设置为新的GenericPrincipal
将为您提供一个用户对象,但不是一个配置文件对象,并且ProfileBase.Create(userName)
和HttpContext.Current.Profile
仍将指向新的空对象。
如果您希望在同一个请求中为新创建的用户创建配置文件,则需要调用HttpContext.Current.Profile.Initialize(userName, true)
。然后,您可以填充初始化的概要文件并保存它,将来的请求可以通过名称来访问它,因此Joel的代码将会工作。当我需要在创建后立即创建/访问配置文件时,我只在内部使用HttpContext.Current.Profile
。对于任何其他请求,我使用ProfileBase.Create(userName)
,并且只将该版本公开为公共版本。
请注意,Franci是正确的:如果您愿意创建用户(和角色),并在第一次往返中将其设置为经过身份验证,然后要求用户登录,那么您将能够更简单地通过Joel在后续请求中的代码访问配置文件。让我吃惊的是,角色可以在用户创建时立即访问,而不需要任何初始化,但配置文件不能。
我的新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都会返回对象的一个新实例,无论它是否为现有的概要文件。因为它被定义为属性,所以我没有考虑到这一点,并写道:
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()
。
发布于 2010-03-31 02:01:03
创建用户只会将其添加到用户列表中。但是,这不会对当前请求的新用户进行身份验证或授权。您还需要在当前请求上下文或后续请求中对用户进行身份验证。
Membership.ValidateUser
将仅验证凭据,但不会针对当前或后续请求验证用户身份。FormsAuthentication.SetAuthCookie
将在响应流中设置身份验证票证,因此将对下一个请求进行身份验证,但它不会影响当前请求的状态。
对用户进行身份验证的最简单方法是调用FormsAuthentication.RedirectFromLoginPage
(假设您在应用程序中使用表单身份验证)。但是,这实际上会导致一个新的HTTP请求,该请求将对用户进行身份验证。
或者,如果您需要继续处理当前请求的逻辑,但希望对用户进行身份验证,则可以创建一个GenericPrincipal
,为其分配新用户的身份,并将HttpContext.User
设置为该主体。
发布于 2012-01-22 05:27:32
如果启用anonymousIdentification,您将会遇到这种方法的问题。我建议使用HttpContext.Profile.UserName而不是Membership.GetUser().UserName。
像这样..。
private UserProfile _profile;
private UserProfile Profile
{
get { return _profile ?? (_profile = (UserProfile)ProfileBase.Create(HttpContext.Profile.UserName)); }
}
帽子提示:SqlProfileProvider - can you use Profile.GetProfile() in a project?
发布于 2011-07-02 06:20:11
首先,感谢@Jeremy分享您的发现。你帮我走上了正确的方向。其次,很抱歉撞到了这个老帖子。希望这能帮助一些人把这些点联系起来。
我最终成功的方法是在我的profile类中使用下面的静态方法:
internal static void InitializeNewMerchant(string username, Merchant merchant)
{
var profile = System.Web.HttpContext.Current.Profile as MerchantProfile;
profile.Initialize(username, true);
profile.MerchantId = merchant.MerchantId;
profile.Save();
}
https://stackoverflow.com/questions/2547290
复制相似问题