我正在尝试将示例表配置文件提供程序从http://www.asp.net/downloads/sandbox/table-profile-provider-samples添加到新的MVC 2站点。
经过一番研究和摆弄后,我到达了一个看起来像这样的个人资料类。
namespace MyNamespace.Models
{
public class UserProfile : ProfileBase
{
[SettingsAllowAnonymous(false),CustomProviderData("FirstName;nvarchar")]
public string FirstName
{
get { return base["FirstName"] as string; }
set { base["FirstName"] = value; }
}
[SettingsAllowAnonymous(false),CustomProviderData("LastName;nvarchar")]
public string LastName
{
get { return base["LastName"] as string; }
set { base["LastName"] = value; }
}
public static UserProfile GetUserProfile(string username)
{
return Create(username,false) as UserProfile;
}
public static UserProfile GetUserProfile()
{
return Create(Membership.GetUser().UserName,true) as UserProfile;
}
}
}
和web.config一样
<profile enabled="true" defaultProvider="TableProfileProvider" inherits="MyNamespace.Models.UserProfile">
<providers>
<clear />
<add name="TableProfileProvider" type="Microsoft.Samples.SqlTableProfileProvider" connectionStringName="ContentDB" table="aspnet_UserProfiles" applicationName="/"/>
</providers>
</profile>
我认为我在路上发现的事情是
<profile>
元素的“inherits”属性,这会排除使用具有相同配置文件字段名称的<properties><add ....>
构造。CustomProviderData
属性,并且由于上述原因,它不能出现在web.config文件中,因此需要作为属性添加到概要文件类中的属性。 一旦用户登录,似乎一切正常。但是,我想在新用户注册过程中捕获一些配置文件数据,在用户登录之前,我似乎无法访问配置文件对象。
我尝试在MVC模板代码的新用户注册部分添加一个保存配置文件数据的调用:
FormsService.SignIn(model.UserName, false /* createPersistentCookie */);
UserProfile profile = UserProfile.GetUserProfile(Membership.GetUser().UserName);
profile.FirstName = "Doug";
Profile.Save();
return RedirectToAction("Index", "Home");
然而,在用户实际登录之前,似乎Membership.GetUser()
为空。我也尝试使用模型中的用户名。
FormsService.SignIn(model.UserName, false /* createPersistentCookie */);
UserProfile profile = UserProfile.GetUserProfile(model.UserName);
profile.FirstName = "Doug";
profile.Save();
return RedirectToAction("Index", "Home");
这有点进一步,但在尝试设置FirstName配置文件字段时失败,并显示错误消息“尝试将属性设置为匿名用户,但这是不允许的”(抱歉,不要我可以输入确切的信息,因为我输入了这个。)
这有什么办法吗?就表单身份验证而言,FormsServer.SignIn
方法实际上并没有实际记录用户,并且需要完全登录才能完成,可能需要将cookie提交回服务器。 / p>
如果没有简单的方法,我可以使用数据访问方法直接填充配置文件表(插入到aspnet_UserProfiles ....)。这是一个过头的桥梁,还是一个可行的解决方案?
没有人有这个问题吗?没有?那么就是我!
为了更新,我已经尝试过Franci Penov在回答posting时的建议。
所以,现在我的代码看起来像这样。
FormsService.SignIn(model.UserName, false /* createPersistentCookie */);
GenericIdentity id = new GenericIdentity(model.UserName);
HttpContext.User = new GenericPrincipal(id, null);
UserProfile profile = UserProfile.GetUserProfile(Membership.GetUser().UserName) as UserProfile;
profile.FirstName = "Doug";
profile.Save();
return RedirectToAction("Index", "Home");
现在,至少对Membership.GetUser()的调用会返回一个有效的MembershipUser
对象,但是尝试设置FirstName配置文件属性仍然会生成消息This property cannot be set for anonymous users.
因此,就会员资格而言,用户已登录,但Profile系统仍然认为不是。
有什么想法吗?
答案 0 :(得分:4)
乌拉!
更仔细地阅读这个posting,我想我会尝试明确地调用配置文件Initialize方法,并且它有效!
注册操作方法的最终完整代码是:
[HttpPost]
public ActionResult Register(RegisterModel model)
{
if (ModelState.IsValid)
{
// Attempt to register the user
MembershipCreateStatus createStatus = MembershipService.CreateUser(model.UserName, model.Password, model.Email);
if (createStatus == MembershipCreateStatus.Success)
{
FormsService.SignIn(model.UserName, false /* createPersistentCookie */);
GenericIdentity id = new GenericIdentity(model.UserName);
HttpContext.User = new GenericPrincipal(id, null);
UserProfile profile = UserProfile.GetUserProfile(Membership.GetUser().UserName) as UserProfile;
profile.Initialize(Membership.GetUser().UserName, true);
profile.FirstName = "Doug";
profile.Save();
return RedirectToAction("Index", "Home");
}
else
{
ModelState.AddModelError("", AccountValidation.ErrorCodeToString(createStatus));
}
}
// If we got this far, something failed, redisplay form
ViewData["PasswordLength"] = MembershipService.MinPasswordLength;
return View(model);
}
希望这有帮助。
道格
答案 1 :(得分:0)
我有一个稍微简单的方法解决问题。
我在web.config文件中设置了以下内容:
<profile enabled="true">
<providers>
<clear />
<add name="AspNetSqlProfileProvider" type="System.Web.Profile.SqlProfileProvider" connectionStringName="ApplicationServices" applicationName="/" />
</providers>
<properties>
<add name="InfoID" />
<add name="FirstName" />
<add name="LastName" />
<add name="Address" />
<add name="City" />
<add name="State" />
<add name="PostalCode" />
<add name="Country" />
<add name="Phone" />
</properties>
</profile>
要在我的AccountController类中更新它,我使用了以下内容:
var user = db.UserInformations.FirstOrDefault(u => u.InfoID == infoID);
var profile = Request.RequestContext.HttpContext.Profile;
profile.Initialize(register.UserName, true);
profile.SetPropertyValue("InfoID", user.InfoID.ToString());
profile.SetPropertyValue("LastName", user.LastName);
profile.SetPropertyValue("FirstName", user.FirstName);
profile.SetPropertyValue("Address", user.Address);
profile.SetPropertyValue("City", user.City);
profile.SetPropertyValue("State", user.State);
profile.SetPropertyValue("Country", user.Country);
profile.SetPropertyValue("PostalCode", user.PostalCode);
profile.SetPropertyValue("Phone", user.Phone);
profile.Save();
您可以创建动态包装器并使用配置文件变量初始化它,而不是使用字符串键。
这对我来说很好。它为指定的用户更新标准的aspnet_Profile数据库。我正在从一个登录系统转换为标准登录,因此我有额外的InfoID字段(它链接到另一个数据库)。我在登录时执行此操作以传输信息。
您可能应检查特定用户的信息是否存在于任何字段之前,在登录时不必要地设置它们或仅更新那些需要更改的字段。
注意:您必须首先初始化配置文件,否则任何更改都会导致黄屏错误。