In the
first part of these series we discussed and provided an example of how to
create a custom membership provider. We will continue these mini series with a
discussion and an example of how to create a custom role provider.
We said in the first part that the reason of why you
would like to create a custom membership provider would be if you want to use a
data source different than the one supported or if you need to manage role
information using a database schema that is different from the database schema
used by the providers that ship with the .NET Framework. The reasons of why you
would want to create a ciustom role provider are the same.
In the example that I'm going to provide I use
Linq-to-SQL data source and my own table structure to keep membership/user and
role data.
To implement a custom role provider you need to inherit
from RoleProvider abstract class from
System.Web.Security namespace. The RoleProvider abstract
class inherits the ProviderBase abstract
class from the System.Configuration.Provider namespace.
As a result, you must implement the required members of the ProviderBase class
as well.
Here's the example:
namespace Custom.Role
{
using System;
using System.Linq;
using System.Configuration;
using System.Collections.Specialized;
using System.Configuration.Provider;
using System.Data;
using System.Data.SqlClient;
using System.Security.Cryptography;
using System.Text;
using System.Web.Configuration;
using System.Web.Security;
using System.Collections.Generic;
using Custom.CustomData;
public sealed class CustomRoleProvider : RoleProvider
{
private string applicationName;
public override string ApplicationName
{
get
{
return applicationName;
}
set
{
applicationName = value;
}
}
/// <summary>
/// Initialize.
/// </summary>
/// <param name="usernames"></param>
/// <param name="roleNames"></param>
public override void Initialize(string name, NameValueCollection config)
{
if (config == null)
{
throw new ArgumentNullException("config");
}
if (name == null || name.Length == 0)
{
name = "CustomRoleProvider";
}
if (String.IsNullOrEmpty(config["description"]))
{
config.Remove("description");
config.Add("description", "Custom Role Provider");
}
//Initialize the abstract base class.
base.Initialize(name, config);
applicationName = GetConfigValue(config["applicationName"], System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath);
}
/// <summary>
/// Add users to roles.
/// </summary>
/// <param name="usernames"></param>
/// <param name="roleNames"></param>
public override void AddUsersToRoles(string[] usernames, string[] roleNames)
{
try
{
using (CustomDataDataContext _db = new CustomDataDataContext())
{
foreach (string username in usernames)
{
// find each user in users table
User user = (from u in _db.Users
where u.UserName == username && u.DeletedOn == null
select u)
.FirstOrDefault();
if (user != null)
{
// find all roles that are contained in the roleNames
var AllDbRoles = (from r in _db.Roles select r).ToList();
List<int> UserRoles = new List<int>();
foreach (var role in AllDbRoles)
{
foreach (string roleName in roleNames)
{
if (role.RoleName == roleName)
{
UserRoles.Add(role.RoleId);
continue;
}
}
}
if (UserRoles.Count > 0)
{
foreach (var roleId in UserRoles)
{
UserInRole UIR = (from uir in _db.UserInRoles
where uir.UserFK == user.UserId && uir.RoleFK == roleId
select uir).FirstOrDefault();
if (UIR == null)
{
UIR = new UserInRole();
UIR.UserFK = user.UserId;
UIR.RoleFK = roleId;
UIR.CreatedOn = DateTime.Now;
UIR.DeletedOn = null;
_db.UserInRoles.InsertOnSubmit(UIR);
_db.SubmitChanges();
}
else
{
UIR.DeletedOn = null;
_db.SubmitChanges();
}
}
}
}
}
}
}
catch
{
}
}
/// <summary>
/// Create new role.
/// </summary>
/// <param name="roleName"></param>
public override void CreateRole(string roleName)
{
try
{
using (CustomDataDataContext _db = new CustomDataDataContext())
{
Role role = new Role();
role.RoleName = roleName;
_db.Roles.InsertOnSubmit(role);
_db.SubmitChanges();
}
}
catch
{
}
}
/// <summary>
/// Delete role.
/// </summary>
/// <param name="roleName"></param>
/// <param name="throwOnPopulatedRole"></param>
/// <returns>true if role is successfully deleted</returns>
public override bool DeleteRole(string roleName, bool throwOnPopulatedRole)
{
bool ret = false;
using (CustomDataDataContext _db = new CustomDataDataContext())
{
try
{
Role role = (from r in _db.Roles
where r.RoleName == roleName
select r).SingleOrDefault();
if (role != null)
{
_db.Roles.DeleteOnSubmit(role);
_db.SubmitChanges();
ret = true;
}
}
catch
{
ret = false;
}
}
return ret;
}
/// <summary>
/// Find users in role.
/// </summary>
/// <param name="roleName"></param>
/// <param name="usernameToMatch"></param>
/// <returns></returns>
public override string[] FindUsersInRole(string roleName, string usernameToMatch)
{
List<string> users = new List<string>();
using (CustomDataDataContext _db = new CustomDataDataContext())
{
try
{
var usersInRole = from uir in _db.UserInRoles
where uir.Role.RoleName == roleName && uir.User.UserName == usernameToMatch
select uir;
if (usersInRole != null)
{
foreach (var userInRole in usersInRole)
{
users.Add(userInRole.User.UserName);
}
}
}
catch
{
}
}
return users.ToArray();
}
/// <summary>
/// Get all roles.
/// </summary>
/// <returns></returns>
public override string[] GetAllRoles()
{
List<string> roles = new List<string>();
using (CustomDataDataContext _db = new CustomDataDataContext())
{
try
{
var dbRoles = from r in _db.Roles
select r;
foreach (var role in dbRoles)
{
roles.Add(role.RoleName);
}
}
catch
{
}
}
return roles.ToArray();
}
/// <summary>
/// Get all roles for a specific user.
/// </summary>
/// <param name="username"></param>
/// <returns></returns>
public override string[] GetRolesForUser(string username)
{
List<string> roles = new List<string>();
using (CustomDataDataContext _db = new CustomDataDataContext())
{
try
{
var dbRoles = from r in _db.UserInRoles
where r.User.UserName == username
select r;
foreach (var role in dbRoles)
{
roles.Add(role.Role.RoleName);
}
}
catch
{
}
}
return roles.ToArray();
}
/// <summary>
/// Get all users that belong to a role.
/// </summary>
/// <param name="roleName"></param>
/// <returns></returns>
public override string[] GetUsersInRole(string roleName)
{
List<string> users = new List<string>();
using (CustomDataDataContext _db = new CustomDataDataContext())
{
try
{
var usersInRole = from uir in _db.UserInRoles
where uir.Role.RoleName == roleName
select uir;
if (usersInRole != null)
{
foreach (var userInRole in usersInRole)
{
users.Add(userInRole.User.UserName);
}
}
}
catch
{
}
}
return users.ToArray();
}
/// <summary>
/// Checks if user belongs to a given role.
/// </summary>
/// <param name="username"></param>
/// <param name="roleName"></param>
/// <returns></returns>
public override bool IsUserInRole(string username, string roleName)
{
bool isValid = false;
using (CustomDataDataContext _db = new CustomDataDataContext())
{
try
{
var usersInRole = from uir in _db.UserInRoles
where uir.User.UserName == username && uir.Role.RoleName == roleName
select uir;
if (usersInRole != null)
{
isValid = true;
}
}
catch
{
isValid = false;
}
}
return isValid;
}
/// <summary>
///
/// </summary>
/// <param name="usernames"></param>
/// <param name="roleNames"></param>
public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames)
{
try
{
using (CustomDataDataContext _db = new CustomDataDataContext())
{
foreach (string username in usernames)
{
// find each user in users table
User user = (from u in _db.Users
where u.UserName == username && u.DeletedOn == null
select u)
.FirstOrDefault();
if (user != null)
{
// find all roles that are contained in the roleNames
var AllDbRoles = (from r in _db.Roles select r).ToList();
List<int> RemoveRoleIds = new List<int>();
foreach (var role in AllDbRoles)
{
foreach (string roleName in roleNames)
{
if (role.RoleName == roleName)
{
RemoveRoleIds.Add(role.RoleId);
continue;
}
}
}
if (RemoveRoleIds.Count > 0)
{
foreach (var roleId in RemoveRoleIds)
{
UserInRole UIR = (from uir in _db.UserInRoles
where uir.UserFK == user.UserId && uir.RoleFK == roleId
select uir).FirstOrDefault();
if (UIR != null)
{
UIR.CreatedOn = DateTime.Now;
UIR.DeletedOn = DateTime.Now;
_db.SubmitChanges();
}
}
}
}
}
}
}
catch
{
}
}
/// <summary>
/// Check if role exists.
/// </summary>
/// <param name="configValue"></param>
/// <param name="defaultValue"></param>
/// <returns></returns>
public override bool RoleExists(string roleName)
{
bool isValid = false;
using (CustomDataDataContext _db = new CustomDataDataContext())
{
// check if role exits
if (_db.Roles.Any(r => r.RoleName == roleName))
{
isValid = true;
}
}
return isValid;
}
/// <summary>
/// Get config value.
/// </summary>
/// <param name="configValue"></param>
/// <param name="defaultValue"></param>
/// <returns></returns>
private string GetConfigValue(string configValue, string defaultValue)
{
if (String.IsNullOrEmpty(configValue))
{
return defaultValue;
}
return configValue;
}
}
}
After we are finished with the code we need to tell the
application that we are going to use a different role provider. We do this by
adding a roleProvider tag to
web.config under system.web:
<roleManager enabled="true" defaultProvider="WaooRoleProvider">
<providers>
<clear />
<add name="CustomRoleProvider" type="Custom.Role.CustomRoleProvider" connectionStringName="CustomConnectionString" applicationName="/" />
</providers>
</roleManager>
...and that's it. You can use ASP.NET controls like
LoginView or Sitemap that work with role providers. These controls are going
to work with your provider now. Of course you can always use it in your code,
whether it's to create a new role or to check if the user belongs to an existing
one:
Roles.RoleExists("SomeRole");
Roles.AddUserToRole("user", "SomeRole");
There you have it. So far we've seen how to provide our
own custom user authentication(a custom membership provider), and how to provide
role based authentication using our own custom role provider that is using our
own data structure.
Next we will see how to extend the information that we
have for a user if the default isn't enough for us.
Until then....Happy programming.
Bojan
Other chapters from these series
Hi Bojan,
ReplyDeletei follow your description and save the file in a folder, as you, but i got the error "could not found...". Where is my mistake?
Thanks, Michael
Thanks a lot Bojan.
ReplyDelete