如何分配配置文件值?


110

我不知道自己缺少什么,但是我在Web.config文件中添加了Profile属性,但是无法访问Profile。在代码中输入项目或创建一个新的配置文件。

Answers:


179

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

Visual Studio中有两种项目-“网站项目”和“ Web应用程序项目”。由于对我来说完全是个谜,Web应用程序项目不能使用Profile。直接...强类型类不是从Web.config文件为您神奇生成的,因此您必须自己滚动。

MSDN中的示例代码假设您使用的是网站项目,他们告诉你只是一个补充<profile>部分,将Web.config和党与Profile.财产,但也不至于在Web应用程序项目的工作。

您有两种选择可以自己滚动:

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

我之所以选择不这样做,是因为我不想让我的代码依赖于这个额外的工具来进行编译,这可能会在其他人尝试构建我的代码而未意识到自己需要此工具时给其他人带来麻烦。

(2)制作自己的派生类,ProfileBase以表示您的自定义配置文件。这比看起来容易。这是一个非常简单的示例,添加了“ FullName”字符串配置文件字段:

在您的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本身不使用配置文件。对于每天有1,000,000次页面浏览的网站,此代码可能不够快。当我写这篇文章时,我正在另一个项目上。
乔尔·斯波斯基

1
这是我自己的错,但是在调用CurrentUser之后,我在设置属性上苦苦挣扎了一段时间。由于CurrentUser每次都会实例化并返回一个新实例,因此我可以建议将其定义为方法吗?我不假思索地写道:AccountProfile.CurrentUser.FullName =“ Snoopy”; AccountProfile.CurrentUser.OtherProperty =“ ABC”; AccountProfile.CurrentUser.Save(); 这不起作用。它应该是:AccountProfile currentProfile = AccountProfile.CurrentUser; currentProfile.FullName =“史努比”; currentProfile.OtherProperty =“ ABC”; currentProfile.Save();
Jeremy Gruenwald

1
这不是要破坏Profile的全部目的吗?您不能使用“ Profile.MyProperty”,而必须使用自己的本地类,而该类并非像Profile那样自动在每个页面上设置。所有这些使您无需编码即可使用Save()功能。
Mike

7
Web应用程序项目不能使用配置文件。
乔尔·斯波斯基

2
如果您不小心在web配置<profile ..><properties><add name="..">中以及AccountProfile类下定义了配置文件属性,则会看到“此属性已定义”,可以通过删除web.config中的属性来轻松解决。
Zachary Scott

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”不包含定义为“保存”
吉米·

2
@Salman:ProfileCommon派生自System.Web.Profile.ProfileBase,它确实具有Save()方法。请检查您的大小写是否正确。请参阅:msdn.microsoft.com/en-us/library/...
colivier

13

概要文件也可以在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对象。概要文件属性无法使用概要文件访问语法如上所述,但是可以通过实例化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

我猜没有人会在这里向下滚动。这是金,谢谢贝德!保存上面的数据后,只需创建一个新ProfileBase对象并调用GetPropertyValue("PropName")?,便可以从任何地方访问用户数据。
seebiscuit 2014年

太神奇了,这是对我有用的唯一方法。Thans Bede
伊曼纽尔·皮罗瓦诺

第一个问题,我该如何在另一个页面中使用get?
伊曼纽尔·皮罗瓦诺

8

当您在Visual Studio中创建新的网站项目时,将从(自动)生成Profile中返回的对象。当您创建Web应用程序项目或MVC项目时,您将不得不自己滚动。

这听起来可能比实际困难。您需要执行以下操作:

  • 使用aspnet_regsql.exe创建数据库此工具与.NET框架一起安装。
  • 编写一个从ProfileGroupBase派生的类,或者安装Web Profile Builder(WPB),它可以从Web.Config中的定义为您生成该类。我一直在使用WPB一段时间,直到现在为止它已经完成了预期的工作。如果您有很多属性,则使用WPB可以节省大量时间。
  • 确保在Web.Config中正确配置了到数据库的连接。
  • 现在您已设置为创建概要文件类的实例(在控制器中)
  • 您可能需要在视图中使用配置文件属性值。我喜欢将配置文件对象本身传递给视图(而不是单个属性)。

3

如果您使用的是Web应用程序项目,则无法在设计时即开即用地访问Profile对象。以下是应该为您执行此操作的实用程序:http : //weblogs.asp.net/joewrobel/archive/2008/02/03/web-profile-builder-for-web-application-projects.aspx。就个人而言,该实用程序在我的项目中引起了错误,因此我最终滚动了自己的配置文件类以从ProfileBase继承。一点也不难。


3
System.Web.Profile-以下是一些示例代码:weblogs.asp.net/jgalloway/archive/2008/01/19/…– nshaw
2009年


2

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

在web.config文件中指定属性,如下所示:- ProfilePropertyWeb.config

现在,编写以下代码:-

配置文件属性后面的代码

编译并运行代码。您将获得以下输出:-

输出量


1

网站的资料创建工作对我来说太棒了。它所生成的类比Joel的帖子中描述的要多得多。我不知道它的实际需要或有用。

无论如何,对于那些寻找一种简单的方法来生成类但又不想拥有外部构建工具依赖项的人,您始终可以

  • 使用网络配置文件构建器
  • 删除所有痕迹!
  • 继续使用生成的Profile类

或(未经测试,但可能会起作用)

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

如果第二种方法行得通,有人可以让我知道以供将来参考


1

只想添加到Joel Spolsky的答案中

我实施了他的解决方案,顺便说一句-Cudos!

对于想要获取不是我使用的已登录用户的用户个人资料的任何人:

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

奇迹般有效...


0

很棒的帖子

只是对web.config的说明,如果您未在profile元素中指定继承属性,则需要在web.config的profile元素内指定每个单独的profile属性,如下所示

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

 </properties>
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.