Я реализовал пользовательский объект Profile в коде, как описано Джоэлем здесь:
Как назначить значения профиля?
Однако я не могу заставить его работать, когда создаю нового пользователя. Когда я делаю это:
Membership.CreateUser(userName, password);
Roles.AddUserToRole(userName, "MyRole");
пользователь создан и добавлен к роли в базе данных, но HttpContext.Current.User
все еще пуст, а Membership.GetUser()
возвращает ноль, так что это (из кода Джоэла) не работает:
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 моего браузера).
решено (отредактировано, см. Ниже): Основываясь на объяснениях Франци Пенова и еще нескольких экспериментах, я выяснил проблему. Код Джоэла и варианты, которые я попробовал, будут работать только с существующим профилем. Если профиль не существует, ProfileBase.Create(userName)
будет возвращать новый пустой объект каждый раз, когда он вызывается; Вы можете установить свойства, но они не будут «прилипать», потому что новый экземпляр возвращается каждый раз, когда вы обращаетесь к нему. Установка HttpContext.Current.User
на новый GenericPrincipal
даст объект User, но not объект профиля, а ProfileBase.Create(userName)
и HttpContext.Current.Profile
будут все еще указывать на новый, пустой объекты.
Если вы хотите создать профиль для вновь созданного пользователя по тому же запросу, вам нужно позвонить HttpContext.Current.Profile.Initialize(userName, true)
. Затем вы можете заполнить инициализированный профиль и сохранить его, и он будет доступен для будущих запросов по имени, поэтому код Джоэла будет работать. Я только , использую HttpContext.Current.Profile
для внутреннего использования, когда мне нужно создать / получить доступ к профилю сразу после создания. В любых других запросах я использую ProfileBase.Create(userName)
, и я выставил только эту версию как общедоступную.
Обратите внимание, что Франси прав: если вы хотите создать пользователя (и роли) и установить его как Аутентифицированный в первом круговом обращении, а затем попросить пользователя войти в систему, вы сможете получить доступ к профилю. гораздо проще через код Джоэла по последующему запросу. Меня бросило то, что роли сразу же становятся доступны при создании пользователя без какой-либо инициализации, но профиль - нет.
Мой новый аккаунтКод профиля:
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()
.