我不知道我缺少什么,但我已经在Web.config文件中添加了Profile属性,但无法在代码中访问Profile.Item或创建新的配置文件。
我不知道我缺少什么,但我已经在Web.config文件中添加了Profile属性,但无法在代码中访问Profile.Item或创建新的配置文件。
今天我遇到了同样的问题,并学到了很多。
在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;
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。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
并使用ProfilePropertySettings
和ProfilePropertySettingsColletion
创建各个属性,可以通过程序来创建配置文件部分。这些类都位于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();
我之前也遇到了同样的问题。但是我没有创建一个继承自ProfileBase的类,而是使用了HttpContext。
在web.config文件中指定属性如下:
现在,编写以下代码:
编译并运行代码。你将得到以下输出:
我想补充一下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(); }
}
}
}
效果非常好...
Web Profile Builder 对我来说非常好用。它生成的类比 Joel 的文章描述的要多得多。不知道它是否真的有用或者必要。
无论如何,对于那些想要轻松生成类,但又不想依赖外部构建工具的人,你总可以:
或者(未经测试但可能有效):
如果这种第二种方法有效,请有人告诉我以备将来参考。
很棒的文章,
关于web.config的一点说明:如果您在profile元素中不指定inherit属性,则需要在web.config中的每个单独的profile属性内指定,如下所示:
<properties>
<clear/>
<add name="property-name-1" />
<add name="property-name-2" />
..........
</properties>
<profile ..><properties><add name="..">
下定义了配置文件属性,并且在 AccountProfile 类中也有定义,那么您会收到一个“该属性已经被定义”的错误信息。通过删除 web.config 中的属性来轻松解决此问题。 - Zachary Scott