2010-06-21 73 views
3

我试图将示例表配置文件提供程序从http://www.asp.net/downloads/sandbox/table-profile-provider-samples添加到新的MVC 2站点。ASP.NET MVC 2和SQL表配置文件提供程序

经过一番研究和摆弄,我已经到了一个看起来像这样的配置文件类。

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; 
     } 
    } 
} 

而像

<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> 

事情的web.config我觉得我的人生路上发现有

  • 使用与MVC定制的提供者要求“继承”属性位于web.config中的<profile>元素上,该元素排除使用具有相同配置文件字段名称的<properties><add ....>构造。
  • 示例SQL表配置文件提供程序需要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"); 

这进一步得到了一点,但未能当试图设置姓轮廓领域,随着沿着线的错误信息“试图设置一个属性作为匿名用户,但是这是不允许的”(对不起,我没有输入这个确切的信息)。

有没有什么办法呢?它看起来像FormsServer.SignIn方法实际上并没有记录用户,只要表单身份验证,它需要一个往返才能完全登录,可能需要将cookie提交回服务器。

如果没有简单的方法,我可以使用数据访问方法直接填充配置文件表(插入到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"); 

现在,至少需要致电会员。的getUser()返回一个有效MembershipUser对象,但试图设置姓配置文件属性仍然会导致消息This property cannot be set for anonymous users.

所以,用户只要成员而言登录,但档案系统仍然认为没有。

任何想法?

+0

好东西,非常有用,谢谢。 只想补充一点,您可能希望在自定义配置文件类的属性设置器中包含this.Save()方法。当我试图找出为什么我的更改没有持续时,我发现这很有帮助。 – randomsequence 2011-07-08 13:42:16

+0

嗨@Doug,伟大的职位!我想知道是否使用tableprofileprovider创建了匿名标识的解决方案。它似乎工作很好,当用户通过身份验证,但我想不出如何与匿名用户合作,以​​登录到他们的配置文件的东西,如语言等。在获得他们注册之前... – 2012-01-11 13:41:23

回答

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); 
} 

希望这有助于。

Doug

+0

你帮我很多! brgds – 2011-12-09 22:56:09

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(); 

而不是使用字符串键,你可以创建一个动态包装并用profile变量初始化它。

这对我来说很好。它为用户指定的用户更新标准的aspnet_Profile数据库。我从一个登录系统转换到标准登录,所以我有额外的InfoID字段(它链接到另一个数据库)。我在登录时通过这种方式传输信息。

您应该先检查特定用户的信息是否存在于任何字段,然后在登录时进行不必要的设置或仅更新那些需要更改的字段。

注意:您必须首先初始化配置文件,否则任何更改都会导致黄色屏幕错误。

相关问题