最近在学习ASP.NET,发现了几个有趣的类,比如自定义用户配置提供程序ProfileProvider,成员提供程序MembershipProvider,角色管理RoleProvider,会话状态SessionStateStoreProvider,这几个类经常作为权限相关设置,但是默认这几个类都必须使用定制的数据库,因此造成诸多限制
但如果重写这些类,然后配合.NET原有的API来使用,这样一来用着方便,二来由于提供程序是自定义的,能够满足自己的要求
于是小弟我试着重写这些类,分享自己的一些心得体会,希望各位前辈能够多多指教啦
前言
最近在学习ASP.NET,发现了几个有趣的类,比如自定义用户配置提供程序ProfileProvider,成员提供程序MembershipProvider,角色管理RoleProvider,会话状态SessionStateStoreProvider,这几个类经常作为权限相关设置,但是默认这几个类都必须使用定制的数据库,因此造成诸多限制
但如果重写这些类,然后配合.NET原有的API来使用,这样一来用着方便,二来由于提供程序是自定义的,能够满足自己的要求
于是小弟我试着重写这些类,分享自己的一些心得体会,希望各位前辈能够多多指教啦
实现自定义用户配置提供程序ProfileProvider
一。说明
在ASP.NET中,可以在web.config文件设置用户个性配置,然后在代码中这么写

Code
using System.Web.Profile;
protected void Page_Load(object sender, EventArgs e)
{
Profile.A = 123;
Profile.B = "wahahaha";
}
这样看似确实很方便,但是缺点就是如果要使用这个用户个性配置,默认是使用SqlProfileProvider,连数据库相关的表都被定死了
唯一的办法就是重写此类,然后让其支持自定义数据库,甚至是支持XML,TXT或者能够想到的任何可以存储信息的媒介
在重写之前,首先要了解该类的一些需要重写的方法和属性
属性
string ApplicationName{get,set} 返回和设置应用程序名
string Name{get} 返回提供程序的名称
string Description{get} 返回一些描述
方法
void Initialize(string name, System.Collections.Specialized.NameValueCollection config) 初始化用的
int DeleteProfiles(string[] usernames) 根据用户名集合来删除用户的个性信息,并返回影响行数
int DeleteProfiles(ProfileInfoCollection profiles) 根据用户信息来删除用户的个性信息,并返回影响行数
ProfileInfoCollection GetAllProfiles(ProfileAuthenticationOption authenticationOption, int pageIndex, int pageSize, out int totalRecords) 获取所有的个性信息,ProfileAuthenticationOption 枚举用于定义是返回匿名用户的还是登陆用户的还是全部的,两个INT型参数用于分页,最后的那个INT参数用于获取返回的行的总数
int DeleteInactiveProfiles(ProfileAuthenticationOption authenticationOption, DateTime userInactiveSinceDate) 删除超时用户的信息
SettingsPropertyValueCollection GetPropertyValues(SettingsContext context, SettingsPropertyCollection collection) 返回当前用户的个性信息
void SetPropertyValues(SettingsContext context, SettingsPropertyValueCollection collection) 设置当前用户的个性信息
还有4个方法,比如
GetNumberOfInactiveProfiles(),FindInactiveProfilesByUserName(),FindProfilesByUserName(),GetAllInactiveProfiles()都是根据条件检索个性信息用的,实现相对简单
二。实现
1.新建立一个项目,然后在App_Data中,添加一个SQL数据库,建立一个表,命名为test1,在表中建立以下字段
UserName varchar 主键
A int (本次实验中自定义的一个字段)
B varchar (本次实验中自定义的一个字段)
IsAnonymous bit 是否为匿名用户
LastActivityDate datetime 最后访问时间
LastUpdateDate datetime 最后更新时间
2.导入sqlCtrl类(此类专门用于操作数据库,源码中有)
3.接下来是关键示例代码

Code
using System.Web.Profile;
public class DefinePro : ProfileProvider
{
public DefinePro()
{
//
//TODO: 在此处添加构造函数逻辑
//
}
private string applicationName;
public override string ApplicationName
{
get
{
return applicationName;
}
set
{
applicationName = value;
}
}
public override string Name
{
get
{
return "DefinePro";
}
}
public override string Description
{
get
{
return "其实没啥好说得";
}
}
public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
{
name = "DefinePro";
base.Initialize(name, config);//调用基类的初始化函数
ApplicationName = System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath;//获得当前应用程序名称
}
public override int DeleteProfiles(string[] usernames)
{
string a = string.Empty;
foreach (string b in usernames)
{
a += "'" + b + "',";
}
a.TrimEnd(',');
try
{
new SqlCtrl().RunCmd("Delete test1 where UserName in(" + a + ")");//从刚才建立得那个数据库中删行
return 1;
}
catch
{
return 0;
}
}
public override int DeleteProfiles(ProfileInfoCollection profiles)
{
try
{
new SqlCtrl().RunCmd("Delete test1 where UserName ='" + profiles["UserName"].ToString() + "'");
return 1;
}
catch
{
return 0;
}
}
public override ProfileInfoCollection GetAllProfiles(ProfileAuthenticationOption authenticationOption, int pageIndex, int pageSize, out int totalRecords)
{
totalRecords = 0;//这里设置为0是因为偷懒
..原本是需要返回查询的行的总数行的总数
ProfileInfoCollection pc = new ProfileInfoCollection();
switch (authenticationOption)
{
case ProfileAuthenticationOption.All:
{
SqlDataReader rd = new SqlCtrl().GetDataReader("Select * from test1 limit " + pageIndex + "," + pageSize);
while (rd.Read())
{
pc.Add(new ProfileInfo(rd[0].ToString(), rd.GetBoolean(3), rd.GetDateTime(4), rd.GetDateTime(5), 0));
}
return pc;
};
break;
case ProfileAuthenticationOption.Anonymous:
{
SqlDataReader rd = new SqlCtrl().GetDataReader("Select * from test1 where IsAnonymous=false limit " + pageIndex + "," + pageSize);
while (rd.Read())
{
pc.Add(new ProfileInfo(rd[0].ToString(), rd.GetBoolean(3), rd.GetDateTime(4), rd.GetDateTime(5), 0));
}
return pc;
};
break;
case ProfileAuthenticationOption.Authenticated:
{
SqlDataReader rd = new SqlCtrl().GetDataReader("Select * from test1 where IsAnonymous=true limit " + pageIndex + "," + pageSize);
while (rd.Read())
{
pc.Add(new ProfileInfo(rd[0].ToString(), rd.GetBoolean(3), rd.GetDateTime(4), rd.GetDateTime(5), 0));
}
return pc;
};
break;
default: return pc; break;
}
}
public override int DeleteInactiveProfiles(ProfileAuthenticationOption authenticationOption, DateTime userInactiveSinceDate)
{
try
{
switch (authenticationOption)
{
case ProfileAuthenticationOption.All: new SqlCtrl().RunCmd("Delete test1 where LastActivityDate <" + userInactiveSinceDate.ToString()); break;
case ProfileAuthenticationOption.Anonymous: new SqlCtrl().RunCmd("Delete test1 where IsAnonymous=false and LastActivityDate <" + userInactiveSinceDate.ToString()); break;
case ProfileAuthenticationOption.Authenticated: new SqlCtrl().RunCmd("Delete test1 where IsAnonymous=true and LastActivityDate <" + userInactiveSinceDate.ToString()); break;
}
return 1;//这里返回1表示操作成功
}
catch
{
return 0;//表示操作失败
}
}
public override SettingsPropertyValueCollection GetPropertyValues(SettingsContext context, SettingsPropertyCollection collection)
{
SettingsPropertyValueCollection spvc = new SettingsPropertyValueCollection();
SqlCtrl sc = new SqlCtrl();
SqlDataReader sr = sc.GetDataReader("Select * from test1 where UserName='" + context["UserName"].ToString() + "'");
int a = 0;
string b = string.Empty;
if (sr.Read())
{
a = sr.GetInt32(1);
b = sr.GetString(2);
}
foreach (SettingsProperty prop in collection)
{
SettingsPropertyValue pv = new SettingsPropertyValue(prop);
switch (prop.Name)
{
case "A": pv.PropertyValue = a; break;
case "B": pv.PropertyValue = b; break;
}
spvc.Add(pv);
}
//在retrun之前,这里明显还要设置一下更新激活时间语句,但时间关系所以省略了。。
return spvc;
}
public override void SetPropertyValues(SettingsContext context, SettingsPropertyValueCollection collection)
{
SqlCtrl sc = new SqlCtrl();
SqlDataReader a = sc.GetDataReader("Select * from test1 where UserName='" + context["UserName"].ToString() + "'");
//如果有行就更新,没行就新建
if (a.Read())
{
a.Dispose();
sc.RunCmd("update test1 set A=" + Convert.ToInt32(collection["A"].PropertyValue) + ",B='" + collection["B"].PropertyValue.ToString() + "',LastActivityDate='" + DateTime.Now.ToString() + "',LastUpdatedDate='" + DateTime.Now.ToString() + "' where UserName='" + context["UserName"].ToString() + "'");
}
else
{
string cc = "insert into test1 (UserName,A,B,IsAnonymous,LastActivityDate,LastUpdatedDate) values ('" + context["UserName"].ToString() + "'," + collection["A"].PropertyValue.ToString() + ",'" + collection["B"].PropertyValue.ToString() + "wc" + "','" + !((bool)(context["IsAuthenticated"])) + "','" + DateTime.Now.ToString() + "','" + DateTime.Now.ToString() + "')";
a.Dispose();
sc.RunCmd(cc);
}
}
}
4.修改Web.config文件

Code
<configuration>
<appSettings/>
<connectionStrings>
<add name="ConnectionString1" connectionString="Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\Database.mdf;Integrated Security=True;User Instance=True" providerName="System.Data.SqlClient"/>
</connectionStrings>
<system.web>
<compilation debug="true">
</compilation>
<authentication mode="Windows"/>
<anonymousIdentification enabled="true"/>
<profile defaultProvider="DefinePro">
<providers>
<clear/>
<add name="DefinePro" type="DefinePro" connectionStringName="ConnectionString1" />
<!--关键就是这里的type="DefinePro" 就可以使用了 -->
</providers>
<properties>
<add name="A" allowAnonymous="true" type="System.Int32"/>
<add name="B" allowAnonymous="true"/>
</properties>
</profile>
</system.web>
</configuration>
5.接下来就可以直接使用了

Code
using System.Web.Profile;
protected void Page_Load(object sender, EventArgs e)
{
Profile.A = 123;
Profile.B = "wahahaha";
}
源码下载
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?