如何分配个人资料值?

110

我不知道我缺少什么,但我已经在Web.config文件中添加了Profile属性,但无法在代码中访问Profile.Item或创建新的配置文件。

10个回答

179

今天我遇到了同样的问题,并学到了很多。

在Visual Studio中有两种类型的项目,即“Web Site Projects”和“Web Application Projects”。出于我完全无法理解的原因,“Web Application Projects”不能直接使用Profile。,因为强类型类不会从Web.config文件中自动生成,所以您必须自己编写代码。

MSDN中的示例代码假定您正在使用Web Site Project,并告诉您只需向Web.config添加一个<profile>节并使用Profile.property继续使用,但在Web Application Projects中无法正常工作。

您有两个选择:

(1)使用Web Profile Builder。这是一种自定义工具,您可以将其添加到Visual Studio中,它可以根据Web.config中的定义自动生成所需的Profile对象。

我选择不这样做,因为我不想让我的代码依赖于此额外的工具来编译,否则当其他人尝试构建我的代码时,可能会遇到需要此工具的问题而不自知。

(2)创建一个继承自ProfileBase的自定义Profile类。这比看起来要容易得多。以下是一个非常简单的示例,它添加了一个“FullName”字符串Profile字段:

在您的web.config中:

<profile defaultProvider="SqlProvider" inherits="YourNamespace.AccountProfile">

<providers>
     <clear />
     <add name="SqlProvider"
          type="System.Web.Profile.SqlProfileProvider"
          connectionStringName="sqlServerMembership" />
</providers>

</profile>

在名为AccountProfile.cs的文件中:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Profile;
using System.Web.Security;

namespace YourNamespace
{
    public class AccountProfile : ProfileBase
    {
        static public AccountProfile CurrentUser
        {
            get { return (AccountProfile)
                         (ProfileBase.Create(Membership.GetUser().UserName)); }
        }

        public string FullName
        {
            get { return ((string)(base["FullName"])); }
            set { base["FullName"] = value; Save(); }
        }

        // add additional properties here
    }
}

设置个人资料的值:

AccountProfile.CurrentUser.FullName = "Snoopy";

获取配置文件值

string x = AccountProfile.CurrentUser.FullName;

10
StackOverflow本身不使用个人资料页面。这段代码可能不够快,无法应对每天100万次页面访问量的网站。我在写这段代码时正在处理另一个项目。 - Joel Spolsky
1
这是我的错,但我花了很长时间来设置调用CurrentUser之后的属性。由于CurrentUser每次都会实例化并返回一个新实例,所以我可以建议将其定义为方法吗?没有思考,我写了这个:AccountProfile.CurrentUser.FullName = "Snoopy"; AccountProfile.CurrentUser.OtherProperty = "ABC"; AccountProfile.CurrentUser.Save();这不起作用。应该是:AccountProfile currentProfile = AccountProfile.CurrentUser; currentProfile.FullName = "Snoopy"; currentProfile.OtherProperty = "ABC"; currentProfile.Save(); - Jeremy Gruenwald
1
这不是有点违背 Profile 的初衷吗?你不能使用“Profile.MyProperty”,而必须使用自己编写的类,而这个类并没有像 Profile 自动设置在每个页面上。这样做只是让你能够利用 Save() 功能,而无需编写代码。 - Mike K
7
Web应用程序项目无法使用个人资料。 - Joel Spolsky
2
如果您不小心在 web.config 文件的 <profile ..><properties><add name=".."> 下定义了配置文件属性,并且在 AccountProfile 类中也有定义,那么您会收到一个“该属性已经被定义”的错误信息。通过删除 web.config 中的属性来轻松解决此问题。 - Zachary Scott
显示剩余10条评论

17

Web应用程序项目仍然可以在运行时使用ProfileCommon对象。它的代码只是不会在项目本身中生成,但ASP.Net会在运行时生成该类。

获取此对象最简单的方法是使用动态类型,如下所示:

在Web.config文件中声明配置文件属性:

<profile ...
 <properties>
   <add name="GivenName"/>
   <add name="Surname"/>
 </properties>

然后访问这些属性:

dynamic profile = ProfileBase.Create(Membership.GetUser().UserName);
string s = profile.GivenName;
profile.Surname = "Smith";

保存个人资料属性更改:

profile.Save();

如果您熟悉使用动态类型且不介意缺乏编译时检查和智能感知,上述方法可以正常工作。

如果您在ASP.Net MVC中使用此方法并将动态配置文件对象传递给视图,则需要进行一些额外的工作,因为HTML助手方法无法与动态“模型”对象很好地配合使用。您需要将配置文件属性分配给静态类型变量,然后再将它们传递给HTML助手方法。

// model is of type dynamic and was passed in from the controller
@Html.TextBox("Surname", model.Surname) <-- this breaks

@{ string sn = model.Surname; }
@Html.TextBox("Surname", sn); <-- will work
如果您创建了自定义的配置文件类(如Joel上面描述的那样),ASP.Net仍然会生成ProfileCommon类,但它将继承自您的自定义配置文件类。如果您没有指定自定义配置文件类,ProfileCommon将继承自System.Web.Profile.ProfileBase。
如果您创建自己的配置文件类,请确保不要在Web.config文件中指定您已经在自定义配置文件类中声明的配置文件属性。如果这样做,当ASP.Net尝试生成ProfileCommon类时,它将会给出一个编译器错误。

我无法保存个人资料。错误是:“ProfileCommon”不包含“save”的定义 - Sal-laS
2
@Salman:ProfileCommon是从System.Web.Profile.ProfileBase派生而来的,它确实有一个Save()方法。请检查您的大小写是否正确。参见:http://msdn.microsoft.com/en-us/library/system.web.profile.profilebase.save(v=vs.110).aspx - colivier

13

Profile可以在Web应用程序项目中使用。这些属性可以在设计时在Web.config文件中定义,也可以以编程方式进行定义。在Web.config文件中:

<profile enabled="true" automaticSaveEnabled="true" defaultProvider="AspNetSqlProfileProvider">
      <providers>
        <clear/>
        <add name="AspNetSqlProfileProvider" type="System.Web.Profile.SqlProfileProvider" connectionStringName="ApplicationServices" applicationName="TestRolesNProfiles"/>
      </providers>
      <properties>
        <add name="FirstName"/>
        <add name="LastName"/>
        <add name ="Street"/>
        <add name="Address2"/>
        <add name="City"/>
        <add name="ZIP"/>
        <add name="HomePhone"/>
        <add name="MobilePhone"/>
        <add name="DOB"/>

      </properties>
    </profile>

通过实例化ProfileSection并使用ProfilePropertySettingsProfilePropertySettingsColletion创建各个属性,可以通过程序来创建配置文件部分。这些类都位于System.Web.Configuration命名空间中。 要使用配置文件部分的属性,需要使用System.Web.Profile.ProfileBase对象。无法像上面提到的profile.语法一样访问配置文件属性,但是可以通过实例化ProfileBase并使用以下代码来轻松完成: SetPropertyValue("PropertyName")GetPropertyValue("PropertyName")

ProfileBase curProfile = ProfileBase.Create("MyName");

或者访问当前用户的配置文件:

ProfileBase curProfile = ProfileBase.Create(System.Web.Security.Membership.GetUser().UserName);



        curProfile.SetPropertyValue("FirstName", this.txtName.Text);
        curProfile.SetPropertyValue("LastName", this.txtLname.Text);
        curProfile.SetPropertyValue("Street", this.txtStreet.Text);
        curProfile.SetPropertyValue("Address2", this.txtAdd2.Text);
        curProfile.SetPropertyValue("ZIP", this.txtZip.Text);
        curProfile.SetPropertyValue("MobilePhone", txtMphone.Text);
        curProfile.SetPropertyValue("HomePhone", txtHphone.Text);
        curProfile.SetPropertyValue("DOB", txtDob.Text);
        curProfile.Save();

1
我不知道为什么这没有得到1000票。它非常有帮助。 - pghcpa
我猜没有人会费心往下滚动。这真是太好了,感谢Bede!在保存了上述数据之后,我可以通过创建新的“ProfileBase”对象并调用“GetPropertyValue(“ PropName ”)”来从任何地方访问用户数据? - seebiscuit
太棒了,这是唯一适合我的方法。谢谢 Bede。 - Emanuel Pirovano
第一个问题,我怎么在另一个页面使用get方法? - Emanuel Pirovano

8
当你在Visual Studio中创建一个新的Web站点项目时,从Profile返回的对象会(自动)为你生成。如果你创建Web应用程序项目或MVC项目,则需要自己创建。
这听起来可能比实际困难。你需要完成以下步骤:
- 使用aspnet_regsql.exe创建一个数据库。该工具是与.NET框架一起安装的。 - 编写一个从ProfileGroupBase派生的类,或者安装Web Profile Builder (WPB),它可以根据Web.Config中的定义为你生成类。我已经使用WPB一段时间了,到目前为止它一直按照预期运行。如果你有很多属性,使用WPB可以节省相当多的时间。 - 确保在Web.Config中正确配置了与数据库的连接。 - 现在你已经准备好在控制器中创建你的profile类的一个实例。 - 你可能需要在视图中使用profile属性值。我喜欢将profile对象本身传递给视图(而不是单个属性)。

3

3
System.Web.Profile - 这里有一些示例代码:http://weblogs.asp.net/jgalloway/archive/2008/01/19/writing-a-custom-asp-net-profile-class.aspx - nshaw

2

2

我之前也遇到了同样的问题。但是我没有创建一个继承自ProfileBase的类,而是使用了HttpContext。

在web.config文件中指定属性如下:

ProfilePropertyWeb.config

现在,编写以下代码:

Code Behind Profile Properties

编译并运行代码。你将得到以下输出:

Output

1

我想补充一下Joel Spolsky的答案。

我实施了他的解决方案,效果非常好 - 赞!

对于任何想要获取非当前登录用户用户配置文件的人,我使用了:

web.config:

  <connectionStrings>
    <clear />
    <add name="LocalSqlConnection" connectionString="Data Source=***;Database=***;User Id=***;Password=***;Initial Catalog=***;Integrated Security=false" providerName="System.Data.SqlClient" />
  </connectionStrings>

并且

<profile defaultProvider="SqlProvider" inherits="NameSpace.AccountProfile" enabled="true">
  <providers>
    <clear/>
    <add name="SqlProvider" type="System.Web.Profile.SqlProfileProvider" connectionStringName="LocalSqlConnection"/>
  </providers>

然后是我的自定义类:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Profile;
using System.Web.Security;

namespace NameSpace
{
    public class AccountProfile : ProfileBase
    {
        static public AccountProfile CurrentUser
        {
            get
            {
                return (AccountProfile)
                 (ProfileBase.Create(Membership.GetUser().UserName));
            }
        }

        static public AccountProfile GetUser(MembershipUser User)
        {
            return (AccountProfile)
                (ProfileBase.Create(User.UserName));
        }

        /// <summary>
        /// Find user with matching barcode, if no user is found function throws exception
        /// </summary>
        /// <param name="Barcode">The barcode to compare against the user barcode</param>
        /// <returns>The AccountProfile class with matching barcode or null if the user is not found</returns>
        static public AccountProfile GetUser(string Barcode)
        {
            MembershipUserCollection muc = Membership.GetAllUsers();

            foreach (MembershipUser user in muc)
            {
                if (AccountProfile.GetUser(user).Barcode == Barcode)
                {
                    return (AccountProfile)
                        (ProfileBase.Create(user.UserName));
                }
            }
            throw new Exception("User does not exist");
        }

        public bool isOnJob
        {
            get { return (bool)(base["isOnJob"]); }
            set { base["isOnJob"] = value; Save(); }
        }

        public string Barcode
        {
            get { return (string)(base["Barcode"]); }
            set { base["Barcode"] = value; Save(); }
        }
    }
}

效果非常好...


1

Web Profile Builder 对我来说非常好用。它生成的类比 Joel 的文章描述的要多得多。不知道它是否真的有用或者必要。

无论如何,对于那些想要轻松生成类,但又不想依赖外部构建工具的人,你总可以:

  • 使用 Web Profile Builder
  • 删除所有痕迹!
  • 继续使用生成的 Profile 类

或者(未经测试但可能有效):

  • 创建一个 Web 站点项目
  • 创建你的元素
  • 捕获生成的类并将其复制到你的 Web 项目中

如果这种第二种方法有效,请有人告诉我以备将来参考。


0

很棒的文章,

关于web.config的一点说明:如果您在profile元素中不指定inherit属性,则需要在web.config中的每个单独的profile属性内指定,如下所示:

 <properties>
    <clear/>
    <add name="property-name-1" />
    <add name="property-name-2" />
    ..........

 </properties>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接