Я реализовал пользовательский объект Профиля в коде, как описано Joel здесь:
Как присвоить значения Профиля?
Я не могу заставить это работать, когда я создаю нового пользователя, как бы то ни было. Когда я делаю это:
Membership.CreateUser(userName, password);
Roles.AddUserToRole(userName, "MyRole");
пользователь создается и добавляется к роли в базе данных, но HttpContext.Current.User
все еще пусто, и Membership.GetUser()
пустой указатель возвратов, таким образом, это (из кода 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
, и т.д., но текущий пользователь является все еще пустым или анонимным (в зависимости от состояния моих 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 в моей функции проверки, но я возвращаю bool для указания на успех, потому что Пользователь. Идентификационные данные. 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()
.
Создание пользователя просто добавляет его в список пользователей. Однако это не аутентифицирует и не авторизует нового пользователя для текущего запроса. Вам также необходимо аутентифицировать пользователя в контексте текущего запроса или для последующих запросов.
Membership.ValidateUser
только подтверждает учетные данные, но не аутентифицирует пользователя для текущего или последующих запросов. FormsAuthentication.SetAuthCookie
установит билет аутентификации в поток ответа, так что следующий запрос будет аутентифицирован, но это не влияет на состояние текущего запроса.
Самым простым способом аутентификации пользователя был бы вызов FormsAuthentication.RedirectFromLoginPage
(если вы используете аутентификацию форм в своем приложении). Однако этот вызов фактически вызовет новый HTTP-запрос, в результате которого пользователь будет аутентифицирован.
В качестве альтернативы, если вам нужно продолжить логику обработки текущего запроса, но вы хотите, чтобы пользователь был аутентифицирован, вы можете создать GenericPrincipal
, присвоить ему идентификатор нового пользователя и установить HttpContext.User
на этого принципала.