Building a MVC2 Template, Part 13, Finishing the Custom Profile Provider
May 31
.Net, Development Asp.Net Mvc, Nehemiah Project No Comments
In part 13 in the Nehemiah Project series we’ll complete the Custom Profile Provider. The profile provider is a generic storage feature and gives our web application the ability to store unique user information. In the profile we can store such items as a web layout, color scheme, zip code, or billing and shipping addresses.
Then why write the custom profile provider. Well, to give us options. If you don’t like the way the SQLProfileProvider stores data you now have your own method. Or if you need to retrieve the data from an existing database or service you have an example of writing the specs and an implementation that can be modified to suit your needs.
Ok, lets get to the code. There are four properties in the Profile class that are purely for testing purposes. When you replace them with your own custom properties you will need to change the specs. There is one property for each of the types string, int, bool, and DateTime. The code for the Profile class is shown below.
One more thing before we get the actual code. You will notice the Profile class has UserId and UserName. These two fields are present at the moment to make the testing of our specifications easier. I fully expect that we’ll eliminate one of these fields in a future post. I would prefer it be the UserName and not UserId, but the ProfileProvider uses UserName. It would be easy enough to join to the User “table”, but I didn’t want to go that extra step at this point. This is one iteration of refactoring I am leaving in the posts.
The Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Nehemiah.Data.Models
{
public class Profile
{
public virtual Guid UserId { get; set; }
public virtual string UserName { get; set; }
public virtual string ApplicationName { get; set; }
public virtual bool Authenticated { get; set; }
public virtual bool Anonymous { get { return Authenticated == false; } }
public virtual DateTime? LastActivityDate { get; set; }
public virtual DateTime? LastUpdateDate { get; set; }
// Todo: Replace these with your custom profile values
public virtual string StringProperty { get; set; }
public virtual int Int32Property { get; set; }
public virtual bool BooleanProperty { get; set; }
public virtual DateTime DateTimeProperty { get; set; }
public Profile()
{
Authenticated = false;
}
public Profile(string applicationName, Guid userId, string userName, bool authenticated, DateTime? lastActivityDate, DateTime? lastUpdateDate)
: this()
{
ApplicationName = applicationName;
UserId = userId;
UserName = UserName;
Authenticated = authenticated;
LastActivityDate = lastActivityDate;
LastUpdateDate = lastUpdateDate;
}
} // End Class
} // End Namespace
Below is our updated ProviderRepository interface. Because I choose not to expose any method that returns an IQueryable object I have a lot of methods in my repository.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Nehemiah.Data.Models;
namespace Nehemiah.Data
{
public interface IProviderRepository
{
#region - Profile -
bool Add(string applicationName, Profile profile);
IList<Profile> GetAllProfiles(string applicationName, bool authenticated, DateTime inactiveDate);
bool Save(string applicationName, Profile profile);
Profile GetProfileByUserName(string applicationName, string userName);
bool DeleteProfile(string applicationName, string userName);
bool DeleteProfile(string applicationName, Guid userId);
IList<Profile> GetProfileList(string applicationName, int index, int pageSize);
IList<Profile> GetProfileList(string applicationName, bool authenticated, int index, int pageSize);
IList<Profile> GetProfileList(string applicationName, DateTime inactiveDate, int index, int pageSize);
IList<Profile> GetProfileList(string applicationName, bool authenticated, DateTime inactiveDate, int index, int pageSize);
IList<Profile> GetProfileList(string applicationName, string username, int index, int pageSize);
IList<Profile> GetProfileList(string applicationName, bool authenticated, string username, int index, int pageSize);
IList<Profile> GetProfileList(string applicationName, DateTime inactiveDate, string username, int index, int pageSize);
IList<Profile> GetProfileList(string applicationName, bool authenticated, DateTime inactiveDate, string username, int index, int pageSize);
int NumberOfProfiles(string applicationName);
int NumberOfProfiles(string applicationName, bool authenticated);
int NumberOfProfiles(string applicationName, DateTime inactiveDate);
int NumberOfProfiles(string applicationName, DateTime inactiveDate, string userName);
int NumberOfProfiles(string applicationName, bool authenticated, DateTime inactiveDate);
int NumberOfProfiles(string applicationName, string username);
int NumberOfProfiles(string applicationName, bool authenticated, string username);
int NumberOfProfiles(string applicationName, bool authenticated, DateTime inactiveDate, string userName);
#endregion
#region - Role -
bool Add(string applicationName, Role role);
bool DeleteRole(string applicationName, string roleName);
IList<Role> GetAllRoles(string applicationName);
Role GetRoleByRoleName(string applicationName, string roleName);
Role GetRoleByKey(string applicationName, int roleId);
IList<Role> GetRoleList(string applicationName, int index, int pageSize);
IList<Role> GetRoleListByRoleName(string applicationName, string roleName, int index, int pageSize);
int NumberOfRoles(string applicationName);
bool Save(string applicationName, Role role);
IList<Role> GetRolesForUser(string applicationName, Guid userId);
IList<Role> GetRolesForUser(string applicationName, string username);
#endregion
#region - User -
bool Add(string applicationName, User user);
bool DeleteUser(string applicationName, string username);
User GetUserByUserName(string applicationName, string username);
User GetUserByKey(string applicationName, Guid userId);
User GetUserByEmail(string applicationName, string email);
IList<User> GetUserList(string applicationName, int index, int pageSize);
IList<User> GetUserListByEmail(string applicationName, string email, int index, int pageSize);
IList<User> GetUserListByUserName(string applicationName, string username, int index, int pageSize);
int NumberOfUsers(string applicationName);
int NumberOfUsersByEmail(string applicationName, string email);
int NumberOfUsersByUserName(string applicationName, string userName);
int NumberOfUsersOnline(string applicationName, int timeWindow);
bool Save(string applicationName, User user);
IList<User> GetUsersInRole(string applicationName, string rolename);
IList<User> GetUsersInRole(string applicationName, string rolename, string username);
#endregion
#region - UserInRole -
bool AddUserToRole(string applicationName, string userName, string roleName);
int NumberOfUsersInRole(string applicationName, int roleId);
bool DeleteUserInRole(string userName, string roleName);
#endregion
} // End Interface
} // End Namespace
I’ve implemented each of the methods defined in the IProviderRepository interface for accessing profiles. The updated code for our MockProviderRepository is listed below.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Nehemiah.Data;
using Nehemiah.Data.Models;
using System.Web;
namespace Nehemiah.Specs.Repositories
{
public class MockProviderRepository : IProviderRepository
{
IList<User> UserList;
IList<Role> RoleList;
IList<UserInRole> UserInRoleList;
IList<Profile> ProfileList;
public MockProviderRepository()
{
UserList = new List<User>
{
new User { ApplicationName = 'Nehemiah'
, Approved = true
, Comment = 'No comment';
, CreationDate = DateTime.UtcNow
, Email = 'me@there.com'
, FailedPasswordAnswerAttemptCount = 0
, FailedPasswordAnswerAttemptStartWindow = null
, FailedPasswordAttemptCount = 0
, FailedPasswordAttemptWindowStart = null
, LastActivityDate = DateTime.UtcNow
, LastLockedOutDate = null
, LastLoginDate = null
, LastPasswordChangedDate = null
, LockedOut = false
, Online = true
, Password = 'GoodPassword'
, PasswordAnswer = 'Old answer'
, PasswordQuestion = 'This is an old question'
, UserId = new Guid('01234567-89AB-CDEF-0123-456789ABCDEF')
, UserName = 'UserName'
} ,
new User { ApplicationName = 'Nehemiah'
, Approved = true
, Comment = 'No comment'
, CreationDate = DateTime.UtcNow
, Email = 'me2@there.com'
, FailedPasswordAnswerAttemptCount = 0
, FailedPasswordAnswerAttemptStartWindow = null
, FailedPasswordAttemptCount = 0
, FailedPasswordAttemptWindowStart = null
, LastActivityDate = DateTime.UtcNow
, LastLockedOutDate = null
, LastLoginDate = null
, LastPasswordChangedDate = null
, LockedOut = false
, Online = true
, Password = 'GoodPassword'
, PasswordAnswer = 'Old answer'
, PasswordQuestion = 'This is an old question'
, UserId = new Guid('22222222-2222-2222-2222-222222222222')
, UserName = 'UserName2'
} ,
new User { ApplicationName = 'Nehemiah'
, Approved = true
, Comment = 'No comment'
, CreationDate = DateTime.UtcNow
, Email = 'me3@there.com'
, FailedPasswordAnswerAttemptCount = 0
, FailedPasswordAnswerAttemptStartWindow = null
, FailedPasswordAttemptCount = 0
, FailedPasswordAttemptWindowStart = null
, LastActivityDate = null
, LastLockedOutDate = null
, LastLoginDate = null
, LastPasswordChangedDate = null
, LockedOut = false
, Online = false
, Password = 'GoodPassword'
, PasswordAnswer = 'Old answer'
, PasswordQuestion = 'This is an old question'
, UserId = new Guid('33333333-3333-3333-3333-333333333333')
, UserName = 'UserName3'
} ,
new User { ApplicationName = 'Nehemiah'
, Approved = false
, Comment = ''
, CreationDate = DateTime.UtcNow
, Email = 'update@somewhere.com'
, FailedPasswordAnswerAttemptCount = 0
, FailedPasswordAnswerAttemptStartWindow = null
, FailedPasswordAttemptCount = 0
, FailedPasswordAttemptWindowStart = null
, LastActivityDate = null
, LastLockedOutDate = null
, LastLoginDate = null
, LastPasswordChangedDate = null
, LockedOut = true
, Online = false
, Password = 'GoodPassword'
, PasswordAnswer = 'Old answer'
, PasswordQuestion = 'This is an old question'
, UserId = new Guid('44444444-4444-4444-4444-444444444444')
, UserName = 'UpdateUser'
} ,
new User { ApplicationName = 'Nehemiah'
, Approved = false
, Comment = ''
, CreationDate = DateTime.UtcNow
, Email = 'update@somewhere.com'
, FailedPasswordAnswerAttemptCount = 0
, FailedPasswordAnswerAttemptStartWindow = null
, FailedPasswordAttemptCount = 0
, FailedPasswordAttemptWindowStart = null
, LastActivityDate = null
, LastLockedOutDate = null
, LastLoginDate = null
, LastPasswordChangedDate = null
, LockedOut = true
, Online = false
, Password = 'GoodPassword'
, PasswordAnswer = 'Old answer'
, PasswordQuestion = 'This is an old question'
, UserId = new Guid('55555555-5555-5555-5555-555555555555')
, UserName = 'LockedOutUser'
} ,
new User { ApplicationName = 'Nehemiah'
, Approved = false
, Comment = ''
, CreationDate = DateTime.UtcNow
, Email = 'update@somewhere.com'
, FailedPasswordAnswerAttemptCount = 0
, FailedPasswordAnswerAttemptStartWindow = null
, FailedPasswordAttemptCount = 0
, FailedPasswordAttemptWindowStart = null
, LastActivityDate = null
, LastLockedOutDate = null
, LastLoginDate = null
, LastPasswordChangedDate = null
, LockedOut = false
, Online = false
, Password = 'GoodPassword'
, PasswordAnswer = 'Old answer'
, PasswordQuestion = 'This is an old question'
, UserId = new Guid('66666666-6666-6666-6666-666666666666')
, UserName = 'NotApprovedUser'
} ,
new User { ApplicationName = 'Nehemiah'
, Approved = false
, Comment = ''
, CreationDate = DateTime.UtcNow
, Email = 'remove@somewhere.com'
, FailedPasswordAnswerAttemptCount = 0
, FailedPasswordAnswerAttemptStartWindow = null
, FailedPasswordAttemptCount = 0
, FailedPasswordAttemptWindowStart = null
, LastActivityDate = null
, LastLockedOutDate = null
, LastLoginDate = null
, LastPasswordChangedDate = null
, LockedOut = false
, Online = false
, Password = 'GoodPassword'
, PasswordAnswer = 'Old answer'
, PasswordQuestion = 'This is an old question'
, UserId = new Guid('77777777-7777-7777-7777-777777777777')
, UserName = 'RemoveUser1'
} ,
new User { ApplicationName = 'Nehemiah'
, Approved = false
, Comment = ''
, CreationDate = DateTime.UtcNow
, Email = 'remove2@somewhere.com'
, FailedPasswordAnswerAttemptCount = 0
, FailedPasswordAnswerAttemptStartWindow = null
, FailedPasswordAttemptCount = 0
, FailedPasswordAttemptWindowStart = null
, LastActivityDate = null
, LastLockedOutDate = null
, LastLoginDate = null
, LastPasswordChangedDate = null
, LockedOut = false
, Online = false
, Password = 'GoodPassword'
, PasswordAnswer = 'Old answer'
, PasswordQuestion = 'This is an old question'
, UserId = new Guid('88888888-8888-8888-8888-888888888888')
, UserName = 'RemoveUser2'
} ,
new User { ApplicationName = 'Nehemiah'
, Approved = true
, Comment = null
, CreationDate = DateTime.UtcNow
, Email = 'deleteme@delete.com'
, FailedPasswordAnswerAttemptCount = 0
, FailedPasswordAnswerAttemptStartWindow = null
, FailedPasswordAttemptCount = 0
, FailedPasswordAttemptWindowStart = null
, LastActivityDate = null
, LastLockedOutDate = null
, LastLoginDate = null
, LastPasswordChangedDate = null
, LockedOut = false
, Online = false
, Password = 'GoodPassword'
, PasswordAnswer = 'Old answer'
, PasswordQuestion = 'This is an old question'
, UserId = new Guid('11111111-2222-3333-4444-555555555555')
, UserName = 'DeleteMe'
}
};
RoleList = new List<Role>
{
new Role { ApplicationName = 'Nehemiah'
, RoleName = 'Administrator'
, RoleId = 1
} ,
new Role { ApplicationName = 'Nehemiah'
, RoleName = 'Registered'
, RoleId = 2
} ,
new Role { ApplicationName = 'Nehemiah'
, RoleName = 'DeleteRole'
, RoleId = 3
} ,
new Role { ApplicationName = 'Nehemiah'
, RoleName = 'NoUsers'
, RoleId = 4
} ,
new Role { ApplicationName = 'Nehemiah'
, RoleName = 'NewRole1'
, RoleId = 5
} ,
new Role { ApplicationName = 'Nehemiah'
, RoleName = 'NewRole2'
, RoleId = 5
} ,
new Role { ApplicationName = 'Nehemiah'
, RoleName = 'NewRole3'
, RoleId = 6
}
};
UserInRoleList = new List<UserInRole>
{
new UserInRole { RoleId = 1
, UserId = new Guid('01234567-89AB-CDEF-0123-456789ABCDEF')
} ,
new UserInRole { RoleId = 2
, UserId = new Guid('01234567-89AB-CDEF-0123-456789ABCDEF')
} ,
new UserInRole { RoleId = 3
, UserId = new Guid('01234567-89AB-CDEF-0123-456789ABCDEF')
} ,
new UserInRole { RoleId = 2
, UserId = new Guid('22222222-2222-2222-2222-222222222222')
} ,
new UserInRole { RoleId = 2
, UserId = new Guid('33333333-3333-3333-3333-333333333333')
} ,
new UserInRole { RoleId = 2
, UserId = new Guid('44444444-4444-4444-4444-444444444444')
} ,
new UserInRole { RoleId = 2
, UserId = new Guid('55555555-5555-5555-5555-555555555555')
} ,
new UserInRole { RoleId = 3
, UserId = new Guid('55555555-5555-5555-5555-555555555555')
} ,
new UserInRole { RoleId = 1
, UserId = new Guid('77777777-7777-7777-7777-777777777777')
} ,
new UserInRole { RoleId = 2
, UserId = new Guid('77777777-7777-7777-7777-777777777777')
} ,
new UserInRole { RoleId = 1
, UserId = new Guid('88888888-8888-8888-8888-888888888888')
} ,
new UserInRole { RoleId = 2
, UserId = new Guid('88888888-8888-8888-8888-888888888888')
}
};
ProfileList = new List<Profile>
{
new Profile { ApplicationName = 'Nehemiah'
, UserId = new Guid('01234567-89AB-CDEF-0123-456789ABCDEF')
, Authenticated = true
, LastActivityDate = DateTime.UtcNow.AddDays(-8)
, LastUpdateDate = DateTime.UtcNow.AddDays(-8)
, UserName = 'UserName'
, StringProperty = 'ABC'
, Int32Property = 1001
, BooleanProperty = false
, DateTimeProperty = new DateTime(2009, 12, 25, 0, 0, 0, DateTimeKind.Utc)
} ,
new Profile { ApplicationName = 'Nehemiah'
, UserId = new Guid('22222222-2222-2222-2222-222222222222')
, Authenticated = true
, LastActivityDate = DateTime.UtcNow.AddDays(-8)
, LastUpdateDate = DateTime.UtcNow.AddDays(-8)
, UserName = 'UserName2'
, StringProperty = 'ABC'
, Int32Property = 1001
, BooleanProperty = false
, DateTimeProperty = new DateTime(2009, 12, 25, 0, 0, 0, DateTimeKind.Utc)
} ,
new Profile { ApplicationName = 'Nehemiah'
, UserId = new Guid('33333333-3333-3333-3333-333333333333')
, Authenticated = false
, LastActivityDate = DateTime.UtcNow.AddDays(-8)
, LastUpdateDate = DateTime.UtcNow.AddDays(-8)
, UserName = 'UserName3'
, StringProperty = 'ABC'
, Int32Property = 1001
, BooleanProperty = false
, DateTimeProperty = new DateTime(2009, 12, 25, 0, 0, 0, DateTimeKind.Utc)
} ,
new Profile { ApplicationName = 'Nehemiah'
, UserId = new Guid('44444444-4444-4444-4444-444444444444')
, Authenticated = true
, LastActivityDate = DateTime.UtcNow.AddDays(-8)
, LastUpdateDate = DateTime.UtcNow.AddDays(-8)
, UserName = 'UpdateUser'
, StringProperty = 'ABC'
, Int32Property = 1001
, BooleanProperty = false
, DateTimeProperty = new DateTime(2009, 12, 25, 0, 0, 0, DateTimeKind.Utc)
} ,
new Profile { ApplicationName = 'Nehemiah'
, UserId = new Guid('55555555-5555-5555-5555-555555555555')
, Authenticated = true
, LastActivityDate = DateTime.UtcNow.AddDays(-8)
, LastUpdateDate = DateTime.UtcNow.AddDays(-8)
, UserName = 'LockedOutUser'
, StringProperty = 'ABC'
, Int32Property = 1001
, BooleanProperty = false
, DateTimeProperty = new DateTime(2009, 12, 25, 0, 0, 0, DateTimeKind.Utc)
} ,
new Profile { ApplicationName = 'Nehemiah'
, UserId = new Guid('66666666-6666-6666-6666-666666666666')
, Authenticated = true
, LastActivityDate = DateTime.UtcNow.AddDays(-8)
, LastUpdateDate = DateTime.UtcNow.AddDays(-8)
, UserName = 'NotApprovedUser'
, StringProperty = 'ABC'
, Int32Property = 1001
, BooleanProperty = false
, DateTimeProperty = new DateTime(2009, 12, 25, 0, 0, 0, DateTimeKind.Utc)
} ,
new Profile { ApplicationName = 'Nehemiah'
, UserId = new Guid('77777777-7777-7777-7777-777777777777')
, Authenticated = false
, LastActivityDate = DateTime.UtcNow.AddDays(-8)
, LastUpdateDate = DateTime.UtcNow.AddDays(-8)
, UserName = 'RemoveUser1'
, StringProperty = 'ABC'
, Int32Property = 1001
, BooleanProperty = false
, DateTimeProperty = new DateTime(2009, 12, 25, 0, 0, 0, DateTimeKind.Utc)
} ,
new Profile { ApplicationName = 'Nehemiah'
, UserId = new Guid('88888888-8888-8888-8888-888888888888')
, Authenticated = false
, LastActivityDate = DateTime.UtcNow.AddDays(-8)
, LastUpdateDate = DateTime.UtcNow.AddDays(-8)
, UserName = 'RemoveUser2'
, StringProperty = 'ABC'
, Int32Property = 1001
, BooleanProperty = false
, DateTimeProperty = new DateTime(2009, 12, 25, 0, 0, 0, DateTimeKind.Utc)
}
};
}
#region - Profile -
public bool Add(string applicationName, Profile profile)
{
ProfileList.Add(profile);
return true;
}
public bool DeleteProfile(string applicationName, string userName)
{
Profile rec = (from p in ProfileList
join u in UserList on p.UserId equals u.UserId
where u.UserName == userName
select p).Single();
ProfileList.Remove(rec);
return true;
}
public bool DeleteProfile(string applicationName, Guid userId)
{
Profile rec = ProfileList.Where(p => p.ApplicationName == applicationName && p.UserId == userId).SingleOrDefault();
ProfileList.Remove(rec);
return true;
}
public bool Save(string applicationName, Profile profile)
{
bool success = true;
Profile rec = ProfileList.Where(p => p.ApplicationName == applicationName && p.UserName == profile.UserName).SingleOrDefault();
if (rec == null)
{
ProfileList.Add(profile);
}
else
{
ProfileList.Remove(rec);
ProfileList.Add(profile);
}
return success;
}
private IQueryable<Profile> Profiles(string applicationName)
{
return ProfileList.Where(p => p.ApplicationName == applicationName).AsQueryable();
}
public Profile GetProfileByUserName(string applicationName, string userName)
{
return Profiles(applicationName).Where(p => p.UserName == userName).SingleOrDefault();
}
public IList<Profile> GetAllProfiles(string applicationName, bool authenticated, DateTime inactiveDate)
{
return Profiles(applicationName).Where(p => p.Authenticated == authenticated && p.LastActivityDate < inactiveDate).ToList();
}
public IList<Profile> GetProfileList(string applicationName, int index, int pageSize)
{
return Profiles(applicationName).OrderBy(p => p.UserName).ToList();
}
public IList<Profile> GetProfileList(string applicationName, bool authenticated, int index, int pageSize)
{
return Profiles(applicationName).Where(p => p.Authenticated == authenticated).OrderBy(p => p.UserName).ToList();
}
public IList<Profile> GetProfileList(string applicationName, DateTime inactiveDate, int index, int pageSize)
{
return Profiles(applicationName).Where(p => p.LastActivityDate < inactiveDate).OrderBy(p => p.UserName).ToList();
}
public IList<Profile> GetProfileList(string applicationName, bool authenticated, DateTime inactiveDate, int index, int pageSize)
{
return Profiles(applicationName).Where(p => p.Authenticated == authenticated && p.LastActivityDate < inactiveDate).OrderBy(p => p.UserName).ToList();
}
public IList<Profile> GetProfileList(string applicationName, string username, int index, int pageSize)
{
return Profiles(applicationName).Where(p => p.UserName.Contains(username)).OrderBy(p => p.UserName).ToList();
}
public IList<Profile> GetProfileList(string applicationName, bool authenticated, string username, int index, int pageSize)
{
return Profiles(applicationName).Where(p => p.Authenticated == authenticated && p.UserName.Contains(username)).OrderBy(p => p.UserName).ToList();
}
public IList<Profile> GetProfileList(string applicationName, DateTime inactiveDate, string username, int index, int pageSize)
{
return Profiles(applicationName).Where(p => p.LastActivityDate < inactiveDate && p.UserName.Contains(username)).OrderBy(p => p.UserName).ToList();
}
public IList<Profile> GetProfileList(string applicationName, bool authenticated, DateTime inactiveDate, string username, int index, int pageSize)
{
return Profiles(applicationName).Where(p => p.Authenticated == authenticated && p.LastActivityDate < inactiveDate && p.UserName.Contains(username)).OrderBy(p => p.UserName).ToList();
}
public int NumberOfProfiles(string applicationName)
{
return Profiles(applicationName).Count();
}
public int NumberOfProfiles(string applicationName, bool authenticated)
{
return Profiles(applicationName).Where(p => p.Authenticated == authenticated).Count();
}
public int NumberOfProfiles(string applicationName, DateTime inactiveDate)
{
return Profiles(applicationName).Where(p => p.LastActivityDate < inactiveDate).Count();
}
public int NumberOfProfiles(string applicationName, bool authenticated, DateTime inactiveDate)
{
return Profiles(applicationName).Where(p => p.Authenticated == authenticated && p.LastActivityDate < inactiveDate).Count();
}
public int NumberOfProfiles(string applicationName, bool authenticated, string username)
{
return Profiles(applicationName).Where(p => p.Authenticated == authenticated && p.UserName.Contains(username)).Count();
}
public int NumberOfProfiles(string applicationName, bool authenticated, DateTime inactiveDate, string userName)
{
return Profiles(applicationName).Where(p => p.Authenticated == authenticated && p.LastActivityDate < inactiveDate && p.UserName.Contains(userName)).Count();
}
public int NumberOfProfiles(string applicationName, DateTime inactiveDate, string userName)
{
return Profiles(applicationName).Where(p => p.LastActivityDate < inactiveDate && p.UserName.Contains(userName)).Count();
}
public int NumberOfProfiles(string applicationName, string username)
{
return Profiles(applicationName).Where(p => p.UserName.Contains(username) == true).Count();
}
#endregion
#region - Role -
public bool Add(string applicationName, Role role)
{
RoleList.Add(role);
Role rec = RoleList.Where(r => r.ApplicationName == applicationName && r.RoleName == role.RoleName).SingleOrDefault();
return (rec != null);
}
public bool DeleteRole(string applicationName, string roleName)
{
Role rec = RoleList.Where(u => u.ApplicationName == applicationName && u.RoleName == roleName).SingleOrDefault();
RoleList.Remove(rec);
return true;
}
private IQueryable<Role> Roles(string applicationName)
{
return RoleList.Where(u => u.ApplicationName == applicationName).AsQueryable();
}
public IList<Role> GetAllRoles(string applicationName)
{
return Roles(applicationName).OrderBy(r => r.RoleName).ToList();
}
public Role GetRoleByRoleName(string applicationName, string roleName)
{
return Roles(applicationName).Where(u => u.RoleName == roleName).SingleOrDefault();
}
public Role GetRoleByKey(string applicationName, int roleId)
{
return Roles(applicationName).Where(u => u.RoleId == roleId).SingleOrDefault();
}
public IList<Role> GetRoleList(string applicationName, int index, int pageSize)
{
return Roles(applicationName).OrderBy(u => u.RoleName).ToList();
}
public IList<Role> GetRoleListByRoleName(string applicationName, string roleName, int index, int pageSize)
{
return Roles(applicationName).Where(u => u.RoleName.Contains(roleName) || u.RoleName == roleName).OrderBy(u => u.RoleName).ToList();
}
public int NumberOfRoles(string applicationName)
{
return Roles(applicationName).Count();
}
public bool Save(string applicationName, Role role)
{
bool success = true;
Role rec = RoleList.Where(u => u.ApplicationName == applicationName && u.RoleId == role.RoleId).SingleOrDefault();
if (rec == null)
{
RoleList.Add(role);
}
else
{
RoleList.Remove(rec);
RoleList.Add(role);
}
return success;
}
#endregion
#region - User -
public bool Add(string applicationName, User user)
{
UserList.Add(user);
User rec = UserList.Where(u => u.ApplicationName == applicationName && u.UserName == user.UserName).SingleOrDefault();
return (rec != null);
}
public bool DeleteUser(string applicationName, string username)
{
User rec = UserList.Where(u => u.ApplicationName == applicationName && u.UserName == username).SingleOrDefault();
UserList.Remove(rec);
return true;
}
private IQueryable<User> Users(string applicationName)
{
return UserList.Where(u => u.ApplicationName == applicationName).AsQueryable();
}
public User GetUserByEmail(string applicationName, string email)
{
return Users(applicationName).Where(u => u.Email == email).SingleOrDefault();
}
public User GetUserByKey(string applicationName, Guid userId)
{
return Users(applicationName).Where(u => u.UserId == userId).SingleOrDefault();
}
public User GetUserByUserName(string applicationName, string username)
{
return Users(applicationName).Where(u => u.UserName == username).SingleOrDefault();
}
public IList<User> GetUserList(string applicationName, int index, int pageSize)
{
return Users(applicationName).OrderBy(u => u.UserName).ToList();
}
public IList<User> GetUserListByEmail(string applicationName, string email, int index, int pageSize)
{
return Users(applicationName).Where(u => u.Email.Contains(email) || u.Email == email).OrderBy(u => u.Email).ToList();
}
public IList<User> GetUserListByUserName(string applicationName, string username, int index, int pageSize)
{
return Users(applicationName).Where(u => u.UserName.Contains(username) || u.UserName == username).OrderBy(u => u.UserName).ToList();
}
public int NumberOfUsers(string applicationName)
{
return Users(applicationName).Count();
}
public int NumberOfUsersByEmail(string applicationName, string email)
{
return Users(applicationName).Where(u => u.Email.Contains(email)).Count();
}
public int NumberOfUsersByUserName(string applicationName, string userName)
{
return Users(applicationName).Where(u => u.UserName.Contains(userName)).Count();
}
public int NumberOfUsersOnline(string applicationName, int timeWindow)
{
return Users(applicationName).Where(u => u.LastActivityDate >= DateTime.UtcNow.AddMinutes(-1 * timeWindow)).Count();
}
public bool Save(string applicationName, User user)
{
bool success = true;
User rec = UserList.Where(u => u.ApplicationName == applicationName && u.UserId == user.UserId).SingleOrDefault();
if (rec == null)
{
UserList.Add(user);
}
else
{
UserList.Remove(rec);
UserList.Add(user);
}
return success;
}
public IList<User> GetUsersInRole(string applicationName, string rolename)
{
var list = from r in RoleList
join uir in UserInRoleList on r.RoleId equals uir.RoleId
join u in UserList on uir.UserId equals u.UserId
where r.RoleName == rolename
select u;
return list.ToList();
}
public IList<User> GetUsersInRole(string applicationName, string rolename, string username)
{
var list = from r in RoleList
join uir in UserInRoleList on r.RoleId equals uir.RoleId
join u in UserList on uir.UserId equals u.UserId
where r.RoleName == rolename && u.UserName.Contains(username)
select u;
return list.ToList();
}
public bool DeleteUserInRole(string userName, string roleName)
{
var roles = from r in RoleList
join uir in UserInRoleList on r.RoleId equals uir.RoleId
where r.RoleName == roleName
select uir;
foreach (var role in roles)
{
UserInRoleList.Remove(role);
}
return true;
}
#endregion
#region - UserInRole -
private IQueryable<UserInRole> UserInRoles(string applicationName)
{
var list = from r in RoleList
join uir in UserInRoleList on r.RoleId equals uir.RoleId
where r.ApplicationName == applicationName
select uir;
return list.AsQueryable();
}
public int NumberOfUsersInRole(string applicationName, int roleId)
{
return UserInRoles(applicationName).Where(r => r.RoleId == roleId).Count();
}
public IList<Role> GetRolesForUser(string applicationName, Guid userId)
{
var list = from uir in UserInRoles(applicationName)
join r in RoleList on uir.RoleId equals r.RoleId
where uir.UserId == userId
select r;
return list.ToList();
}
public IList<Role> GetRolesForUser(string applicationName, string username)
{
var list = from uir in UserInRoles(applicationName)
join r in RoleList on uir.RoleId equals r.RoleId
join u in UserList on uir.UserId equals u.UserId
where u.UserName == username
select r;
return list.ToList();
}
public bool AddUserToRole(string applicationName, string userName, string roleName)
{
Role role;
User user;
// Cannot add a non-existant user
user = GetUserByUserName(applicationName, userName);
if (user == null)
{
return false;
}
// Cannot add a non-existant role
role = GetRoleByRoleName(applicationName, roleName);
if (role == null)
{
return false;
}
UserInRole userInRole = new UserInRole(user.UserId, role.RoleId);
UserInRoleList.Add(userInRole);
return true;
}
#endregion
} // End Class
} // End Namespace
The Profile Provider has many methods for deleting records. In order to test our specifications I have created a method that will add five profiles to our repository. It’s called in a couple of our specifications to ensure we have records to test with.
The other item in the ProfileProvider that I don’t much care for is the Anonymous property. To me this is negative logic and I hate negative logic. Authenticated users get access to areas of an application that Anonymous users do not. To me this is just one step away from testing for every role but Administrator to see if the user is an administrator, when IsAdmin == true, would be much simpler. I don’t like writing code like:
if (!profile.IsAnonymous)
{
// Do something cool...
}
if (profile.IsAnonymous == false)
{
// Do something cool...
}
Instead I prefer writing positive logic code like below. So I have an Anonymous method that is used when calling ProfileProvider methods and an Authenticated method that is used for everything else.
if (profile.IsAuthenticated)
{
// Do something cool...
}
if (profile.IsAuthenticated == true)
{
// Do something cool...
}
The specifications for the ProfileProvider are listed below.
using System;
using System.Collections.Specialized;
using System.Configuration;
using System.Web.Profile;
using Machine.Specifications;
using Nehemiah.Data;
using Nehemiah.Data.Models;
using Nehemiah.Providers;
using Nehemiah.Specs.Repositories;
namespace Nehemiah.Specs.Providers
{
[Subject('Profile Provider')]
public class profile_provider_initialize_method : ProfileProviderContext
{
It should_set_the_application_name = () =>
{
profileProvider.ApplicationName.ShouldEqual(applicationName);
};
}
[Subject('Profile Provider')]
public class delete_profiles_by_profile_collection_method : ProfileProviderContext
{
It should_delete_all_profiles_specified_in_the_collection = () =>
{
int numDeleted = profileProvider.DeleteProfiles(profileCollection);
numDeleted.ShouldEqual(2);
};
}
[Subject('Profile Provider')]
public class delete_profiles_by_user_method : ProfileProviderContext
{
It should_delete_all_profiles_for_the_specified_users = () =>
{
int numDeleted = profileProvider.DeleteProfiles(deleteUsernames);
numDeleted.ShouldEqual(3);
};
}
[Subject('Profile Provider')]
public class delete_inactive_profiles_method : ProfileProviderContext
{
It should_delete_all_profiles_that_havent_been_access_since_the_specified_date = () =>
{
int numDeleted;
// Add some dummy profiles
AddProfiles();
numDeleted = profileProvider.DeleteInactiveProfiles(ProfileAuthenticationOption.All, inactiveDate);
numDeleted.ShouldEqual(13);
// Add them again
AddProfiles();
numDeleted = profileProvider.DeleteInactiveProfiles(ProfileAuthenticationOption.Anonymous, inactiveDate);
numDeleted.ShouldEqual(3);
numDeleted = profileProvider.DeleteInactiveProfiles(ProfileAuthenticationOption.Authenticated, inactiveDate);
numDeleted.ShouldEqual(2);
};
}
[Subject('Profile Provider')]
public class get_number_of_inactive_profiles_method : ProfileProviderContext
{
It should_return_the_number_of_profiles_that_havent_been_accessed_since_the_specified_date = () =>
{
int count;
// Add some dummy profiles
AddProfiles();
count = profileProvider.GetNumberOfInactiveProfiles(ProfileAuthenticationOption.All, inactiveDate);
count.ShouldEqual(13);
count = profileProvider.GetNumberOfInactiveProfiles(ProfileAuthenticationOption.Anonymous, inactiveDate);
count.ShouldEqual(6);
count = profileProvider.GetNumberOfInactiveProfiles(ProfileAuthenticationOption.Authenticated, inactiveDate);
count.ShouldEqual(7);
};
}
[Subject('Profile Provider')]
public class get_all_profiles_method : ProfileProviderContext
{
It should_return_a_collection_of_all_profiles = () =>
{
int totalRecords;
ProfileInfoCollection profiles;
profiles = profileProvider.GetAllProfiles(ProfileAuthenticationOption.All, 0, 10, out totalRecords);
totalRecords.ShouldEqual(8);
profiles.Count.ShouldEqual(8);
profiles = profileProvider.GetAllProfiles(ProfileAuthenticationOption.Anonymous, 0, 10, out totalRecords);
totalRecords.ShouldEqual(3);
profiles.Count.ShouldEqual(3);
profiles = profileProvider.GetAllProfiles(ProfileAuthenticationOption.Authenticated, 0, 10, out totalRecords);
totalRecords.ShouldEqual(5);
profiles.Count.ShouldEqual(5);
};
}
[Subject('Profile Provider')]
public class get_all_inactive_profiles_method : ProfileProviderContext
{
It should_return_a_collection_of_profiles_that_havent_been_accessed_since_the_specified_date = () =>
{
int totalRecords;
ProfileInfoCollection profiles;
profiles = profileProvider.GetAllInactiveProfiles(ProfileAuthenticationOption.All, inactiveDate, 0, 10, out totalRecords);
totalRecords.ShouldEqual(8);
profiles.Count.ShouldEqual(8);
profiles = profileProvider.GetAllInactiveProfiles(ProfileAuthenticationOption.Anonymous, inactiveDate, 0, 10, out totalRecords);
totalRecords.ShouldEqual(3);
profiles.Count.ShouldEqual(3);
profiles = profileProvider.GetAllInactiveProfiles(ProfileAuthenticationOption.Authenticated, inactiveDate, 0, 10, out totalRecords);
totalRecords.ShouldEqual(5);
profiles.Count.ShouldEqual(5);
};
}
[Subject('Profile Provider')]
public class find_profiles_by_user_name_profiles_method : ProfileProviderContext
{
It should_return_a_collection_of_profiles_whose_user_name_matches_the_specified_pattern = () =>
{
int totalRecords;
ProfileInfoCollection profiles;
totalRecords = providerRepository.NumberOfProfiles(applicationName);
totalRecords.ShouldEqual(8);
profiles = profileProvider.FindProfilesByUserName(ProfileAuthenticationOption.All, findUser, 0, 10, out totalRecords);
totalRecords.ShouldEqual(3);
profiles.Count.ShouldEqual(3);
profiles = profileProvider.FindProfilesByUserName(ProfileAuthenticationOption.Anonymous, findUser, 0, 10, out totalRecords);
totalRecords.ShouldEqual(1);
profiles.Count.ShouldEqual(1);
profiles = profileProvider.FindProfilesByUserName(ProfileAuthenticationOption.Authenticated, findUser, 0, 10, out totalRecords);
totalRecords.ShouldEqual(2);
profiles.Count.ShouldEqual(2);
};
}
[Subject('Profile Provider')]
public class find_inactive_profiles_by_user_name_profiles_method : ProfileProviderContext
{
It should_return_a_collection_of_profiles_whose_user_name_matches_the_specified_pattern_and_hasnt_been_accessed_since_the_specified_date = () =>
{
int totalRecords;
ProfileInfoCollection profiles;
profiles = profileProvider.FindInactiveProfilesByUserName(ProfileAuthenticationOption.All, findUser, inactiveDate, 0, 10, out totalRecords);
totalRecords.ShouldEqual(3);
profiles.Count.ShouldEqual(3);
profiles = profileProvider.FindInactiveProfilesByUserName(ProfileAuthenticationOption.Anonymous, findUser, inactiveDate, 0, 10, out totalRecords);
totalRecords.ShouldEqual(1);
profiles.Count.ShouldEqual(1);
profiles = profileProvider.FindInactiveProfilesByUserName(ProfileAuthenticationOption.Authenticated, findUser, inactiveDate, 0, 10, out totalRecords);
totalRecords.ShouldEqual(2);
profiles.Count.ShouldEqual(2);
};
}
[Subject('Profile Provider')]
public class get_property_values_method : ProfileProviderContext
{
It should_return_the_profile_values_as_a_SettingsPropertyValueCollection = () =>
{
SettingsPropertyCollection properties = new SettingsPropertyCollection();
properties.Add(propString);
properties.Add(propInt);
properties.Add(propBool);
properties.Add(propDate);
contextSettings['UserName'] = findUser;
contextSettings['IsAuthenticated'] = true;
SettingsPropertyValueCollection values = profileProvider.GetPropertyValues(contextSettings, properties);
values.Count.ShouldEqual(4);
values['StringProperty'].PropertyValue.ShouldEqual(profileString);
values['IntProperty'].PropertyValue.ShouldEqual(profileInt);
values['BooleanProperty'].PropertyValue.ShouldEqual(profileBool);
values['DateTimeProperty'].PropertyValue.ShouldEqual(profileDate);
};
}
[Subject('Profile Provider')]
public class set_property_values_method : ProfileProviderContext
{
It should_set_the_profile_values_using_a_SettingsPropertyValueCollection = () =>
{
SettingsPropertyValueCollection properties = new SettingsPropertyValueCollection();
properties.Add(new SettingsPropertyValue(propString));
properties.Add(new SettingsPropertyValue(propInt));
properties.Add(new SettingsPropertyValue(propBool));
properties.Add(new SettingsPropertyValue(propDate));
contextSettings['UserName'] = updateUser;
contextSettings['IsAuthenticated'] = true;
profileProvider.SetPropertyValues(contextSettings, properties);
Profile profile = providerRepository.GetProfileByUserName(applicationName, updateUser);
profile.ShouldNotBeNull();
profile.StringProperty.ShouldEqual('abcdef');
profile.Int32Property.ShouldEqual(37);
profile.BooleanProperty.ShouldEqual(true);
profile.DateTimeProperty.ShouldEqual(new DateTime(1900, 1, 2, 0, 0, 0, 0));
};
}
public abstract class ProfileProviderContext
{
protected static IProviderRepository providerRepository;
// Test Data
protected static string applicationName = 'Nehemiah';
protected static ProfileInfoCollection profileCollection = new ProfileInfoCollection
{
new ProfileInfo('RemoveUser1', false, DateTime.UtcNow, DateTime.UtcNow, 0),
new ProfileInfo('RemoveUser2', false, DateTime.UtcNow, DateTime.UtcNow, 0)
};
protected static string[] deleteUsernames = new string[3] { 'LockedOutUser', 'UpdateUser', 'UserName3' };
protected static SettingsContext contextSettings = new SettingsContext();
protected static SettingsProperty propString;
protected static SettingsProperty propInt;
protected static SettingsProperty propBool;
protected static SettingsProperty propDate;
protected static DateTime inactiveDate = DateTime.UtcNow.AddDays(-7);
protected static string findUser = 'UserName';
protected static string updateUser = 'UpdateUser';
protected static string profileString = 'ABC';
protected static int profileInt = 1001;
protected static bool profileBool = false;
protected static DateTime profileDate = new DateTime(2009, 12, 25, 0, 0, 0, DateTimeKind.Utc);
protected static string name;
protected static ProfileProvider profileProvider;
protected static NameValueCollection config;
Establish context = () =>
{
name = 'Nehemiah';
config = new NameValueCollection();
config.Add('applicationName', applicationName);
providerRepository = new MockProviderRepository();
profileProvider = new NehemiahProfileProvider(providerRepository, applicationName);
profileProvider.Initialize(name, config);
propString = new SettingsProperty('StringProperty', typeof(string), profileProvider, false, 'abcdef', SettingsSerializeAs.String, new SettingsAttributeDictionary(), false, false);
propInt = new SettingsProperty('IntProperty', typeof(int), profileProvider, false, 37, SettingsSerializeAs.String, new SettingsAttributeDictionary(), false, false);
propBool = new SettingsProperty('BooleanProperty', typeof(bool), profileProvider, false, true, SettingsSerializeAs.String, new SettingsAttributeDictionary(), false, false);
propDate = new SettingsProperty('DateTimeProperty', typeof(DateTime), profileProvider, false, new DateTime(1900, 1, 2, 0, 0, 0, 0), SettingsSerializeAs.String, new SettingsAttributeDictionary(), false, false);
};
// Dummy profiles for testing
public static void AddProfiles()
{
DateTime? testDate = inactiveDate.AddMinutes(-1);
providerRepository.Add(applicationName, new Profile(applicationName, new Guid('11111111-1111-1111-1111-000000000001'), 'Profile1', false, testDate, testDate));
providerRepository.Add(applicationName, new Profile(applicationName, new Guid('11111111-1111-1111-1111-000000000002'), 'Profile2', false, testDate, testDate));
providerRepository.Add(applicationName, new Profile(applicationName, new Guid('11111111-1111-1111-1111-000000000003'), 'Profile3', false, testDate, testDate));
providerRepository.Add(applicationName, new Profile(applicationName, new Guid('11111111-1111-1111-1111-000000000004'), 'Profile4', true, testDate, testDate));
providerRepository.Add(applicationName, new Profile(applicationName, new Guid('11111111-1111-1111-1111-000000000005'), 'Profile5', true, testDate, testDate));
}
}
}
If you were to rebuild the solution and read the Report.html file, you should see that none of our methods have been implemented. Paste the following code into the ProfileProvider.cs file in the Nehemiah.Providers project.
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Web.Profile;
using Nehemiah.Data;
using Nehemiah.Data.Models;
using System.Configuration.Provider;
// Refernce URL: http://msdn.microsoft.com/en-us/library/aa479035.aspx
// : http://msdn.microsoft.com/en-us/library/ta63b872.aspx
namespace Nehemiah.Providers
{
public class NehemiahProfileProvider : ProfileProvider
{
#region - Properties -
private string ConnectionString { get; set; }
private IProviderRepository ProviderRepository { get; set; }
private string providerName { get; set; }
// The name of the application using the profile provider. ApplicationName is used to scope
// profile data so that applications can choose whether to share profile data with other
// applications. This property can be read and written.
public override string ApplicationName { get; set; }
#endregion
#region - Constructors -
public NehemiahProfileProvider() : base() { }
public NehemiahProfileProvider(IProviderRepository repository, string applicationName)
: this()
{
ProviderRepository = repository;
ApplicationName = applicationName;
}
#endregion
#region - Methods -
public override void Initialize(string name, NameValueCollection config)
{
if (config == null)
throw new ArgumentNullException('config');
providerName = 'NehemiahProfileProvider';
ApplicationName = (String.IsNullOrEmpty(name)) ? Name : name;
if (String.IsNullOrEmpty(config['description']))
{
config.Remove('description');
config.Add('description', 'Nehemiah Asp.Net MVC profile provider');
}
//Initialize the abstract base class.
base.Initialize(name, config);
// Get our connection string
ConnectionString = ConfigurationManager.AppSettings['Connection'];
}
// Deletes the specified profiles from the data source.
public override int DeleteProfiles(ProfileInfoCollection profiles)
{
int count = 0;
foreach (ProfileInfo profile in profiles)
{
if (ProviderRepository.DeleteProfile(ApplicationName, profile.UserName) == true)
{
count++;
}
}
return count;
}
// Deletes the specified users' profiles from the data source.
public override int DeleteProfiles(string[] userNames)
{
int count = 0;
foreach (string username in userNames)
{
if (ProviderRepository.DeleteProfile(ApplicationName, username) == true)
{
count++;
}
}
return count;
}
// Deletes all inactive profiles-profiles that haven't been accessed since the specified
// date-from the data source.
public override int DeleteInactiveProfiles(ProfileAuthenticationOption authenticationOption, DateTime userInactiveSinceDate)
{
int count = 0;
// Remove anonymous user profiles
if (authenticationOption == ProfileAuthenticationOption.Anonymous || authenticationOption == ProfileAuthenticationOption.All)
{
foreach (Profile profile in ProviderRepository.GetAllProfiles(ApplicationName, false, userInactiveSinceDate))
{
ProviderRepository.DeleteProfile(ApplicationName, profile.UserId);
count++;
}
}
// Remove authenitcated user profiles
if (authenticationOption == ProfileAuthenticationOption.Authenticated || authenticationOption == ProfileAuthenticationOption.All)
{
foreach (Profile profile in ProviderRepository.GetAllProfiles(ApplicationName, true, userInactiveSinceDate))
{
ProviderRepository.DeleteProfile(ApplicationName, profile.UserId);
count++;
}
}
return count;
}
// Returns the number of profiles that haven't been accessed since the specified date.
public override int GetNumberOfInactiveProfiles(ProfileAuthenticationOption authenticationOption, DateTime userInactiveSinceDate)
{
int count = 0;
switch (authenticationOption)
{
case ProfileAuthenticationOption.Anonymous:
count = ProviderRepository.NumberOfProfiles(ApplicationName, false);
break;
case ProfileAuthenticationOption.Authenticated:
count = ProviderRepository.NumberOfProfiles(ApplicationName, true);
break;
case ProfileAuthenticationOption.All:
default:
count = ProviderRepository.NumberOfProfiles(ApplicationName);
break;
}
return count;
}
// Returns a collection of ProfileInfo objects containing administrative information
// about all profiles, including user names and last activity dates.
public override ProfileInfoCollection GetAllProfiles(ProfileAuthenticationOption authenticationOption, int pageIndex, int pageSize, out int totalRecords)
{
ProfileInfoCollection profileCollection = new ProfileInfoCollection();
IList<Profile> profileList; // = new List<Profile>();
switch (authenticationOption)
{
case ProfileAuthenticationOption.Anonymous:
totalRecords = ProviderRepository.NumberOfProfiles(ApplicationName, false);
profileList = ProviderRepository.GetProfileList(ApplicationName, false, pageIndex, pageSize);
break;
case ProfileAuthenticationOption.Authenticated:
totalRecords = ProviderRepository.NumberOfProfiles(ApplicationName, true);
profileList = ProviderRepository.GetProfileList(ApplicationName, true, pageIndex, pageSize);
break;
case ProfileAuthenticationOption.All:
default:
totalRecords = ProviderRepository.NumberOfProfiles(ApplicationName);
profileList = ProviderRepository.GetProfileList(ApplicationName, pageIndex, pageSize);
break;
}
try
{
foreach (Profile profile in profileList)
{
profileCollection.Add(GetProfileInfoFromProfile(profile));
}
}
catch (Exception ex)
{
throw new ProviderException(ex.Message);
}
return profileCollection;
}
// Returns a collection of ProfileInfo objects containing administrative information
// regarding profiles that haven't been accessed since the specified date.
public override ProfileInfoCollection GetAllInactiveProfiles(ProfileAuthenticationOption authenticationOption, DateTime userInactiveSinceDate, int pageIndex, int pageSize, out int totalRecords)
{
ProfileInfoCollection profileCollection = new ProfileInfoCollection();
IList<Profile> profileList; // = new List<Profile>();
switch (authenticationOption)
{
case ProfileAuthenticationOption.Anonymous:
totalRecords = ProviderRepository.NumberOfProfiles(ApplicationName, false, userInactiveSinceDate);
profileList = ProviderRepository.GetProfileList(ApplicationName, false, userInactiveSinceDate, pageIndex, pageSize);
break;
case ProfileAuthenticationOption.Authenticated:
totalRecords = ProviderRepository.NumberOfProfiles(ApplicationName, true, userInactiveSinceDate);
profileList = ProviderRepository.GetProfileList(ApplicationName, true, userInactiveSinceDate, pageIndex, pageSize);
break;
case ProfileAuthenticationOption.All:
default:
totalRecords = ProviderRepository.NumberOfProfiles(ApplicationName, userInactiveSinceDate);
profileList = ProviderRepository.GetProfileList(ApplicationName, userInactiveSinceDate, pageIndex, pageSize);
break;
}
try
{
foreach (Profile profile in profileList)
{
profileCollection.Add(GetProfileInfoFromProfile(profile));
}
}
catch (Exception ex)
{
throw new ProviderException(ex.Message);
}
return profileCollection;
}
// Returns a collection of ProfileInfo objects containing administrative information
// regarding profiles whose user names match a specified pattern.
public override ProfileInfoCollection FindProfilesByUserName(ProfileAuthenticationOption authenticationOption, string usernameToMatch, int pageIndex, int pageSize, out int totalRecords)
{
ProfileInfoCollection profileCollection = new ProfileInfoCollection();
IList<Profile> profileList;
switch (authenticationOption)
{
case ProfileAuthenticationOption.Anonymous:
totalRecords = ProviderRepository.NumberOfProfiles(ApplicationName, false, usernameToMatch);
profileList = ProviderRepository.GetProfileList(ApplicationName, false, usernameToMatch, pageIndex, pageSize);
break;
case ProfileAuthenticationOption.Authenticated:
totalRecords = ProviderRepository.NumberOfProfiles(ApplicationName, true, usernameToMatch);
profileList = ProviderRepository.GetProfileList(ApplicationName, true, usernameToMatch, pageIndex, pageSize);
break;
case ProfileAuthenticationOption.All:
default:
totalRecords = ProviderRepository.NumberOfProfiles(ApplicationName, usernameToMatch);
profileList = ProviderRepository.GetProfileList(ApplicationName, usernameToMatch, pageIndex, pageSize);
break;
}
try
{
foreach (Profile profile in profileList)
{
profileCollection.Add(GetProfileInfoFromProfile(profile));
}
}
catch (Exception ex)
{
throw new ProviderException(ex.Message);
}
return profileCollection;
}
// Returns a collection of ProfileInfo objects containing administrative information
// regarding profiles whose user names match a specified pattern and that haven't been accessed since the specified date.
public override ProfileInfoCollection FindInactiveProfilesByUserName(ProfileAuthenticationOption authenticationOption, string usernameToMatch, DateTime userInactiveSinceDate, int pageIndex, int pageSize, out int totalRecords)
{
ProfileInfoCollection profileCollection = new ProfileInfoCollection();
IList<Profile> profileList; // = new List<Profile>();
switch (authenticationOption)
{
case ProfileAuthenticationOption.Anonymous:
totalRecords = ProviderRepository.NumberOfProfiles(ApplicationName, false, userInactiveSinceDate, usernameToMatch);
profileList = ProviderRepository.GetProfileList(ApplicationName, false, userInactiveSinceDate, usernameToMatch, pageIndex, pageSize);
break;
case ProfileAuthenticationOption.Authenticated:
totalRecords = ProviderRepository.NumberOfProfiles(ApplicationName, true, userInactiveSinceDate, usernameToMatch);
profileList = ProviderRepository.GetProfileList(ApplicationName, true, userInactiveSinceDate, usernameToMatch, pageIndex, pageSize);
break;
case ProfileAuthenticationOption.All:
default:
totalRecords = ProviderRepository.NumberOfProfiles(ApplicationName, userInactiveSinceDate, usernameToMatch);
profileList = ProviderRepository.GetProfileList(ApplicationName, userInactiveSinceDate, usernameToMatch, pageIndex, pageSize);
break;
}
try
{
foreach (Profile profile in profileList)
{
profileCollection.Add(GetProfileInfoFromProfile(profile));
}
}
catch (Exception ex)
{
throw new ProviderException(ex.Message);
}
return profileCollection;
}
// Reads profile property values from the data source and returns them in a
// SettingsPropertyValueCollection. See GetPropertyValues for details.
public override SettingsPropertyValueCollection GetPropertyValues(SettingsContext context, SettingsPropertyCollection properties)
{
// The serializeAs attribute is ignored in this provider implementation.
SettingsPropertyValueCollection svc = new SettingsPropertyValueCollection();
if (properties == null || properties.Count < 1 || context == null)
return svc;
string username = (string)context['UserName'];
bool isAuthenticated = (bool)context['IsAuthenticated'];
Profile profile = ProviderRepository.GetProfileByUserName(ApplicationName, username);
if (profile == null)
{
profile = new Profile(ApplicationName, Guid.Empty, username, isAuthenticated, DateTime.UtcNow, DateTime.UtcNow);
}
foreach (SettingsProperty prop in properties)
{
SettingsPropertyValue pv = new SettingsPropertyValue(prop);
// Todo: Replace these with your profile properties.
switch (prop.Name)
{
case 'StringProperty':
pv.PropertyValue = profile.StringProperty;
pv.IsDirty = false;
pv.Deserialized = true;
break;
case 'IntProperty':
pv.PropertyValue = profile.Int32Property;
pv.IsDirty = false;
pv.Deserialized = true;
break;
case 'BooleanProperty':
pv.PropertyValue = profile.BooleanProperty;
pv.IsDirty = false;
pv.Deserialized = true;
break;
case 'DateTimeProperty':
pv.PropertyValue = profile.DateTimeProperty;
pv.IsDirty = false;
pv.Deserialized = true;
break;
default:
throw new ProviderException(string.Format('Unsupported property {0}.', prop.Name));
}
svc.Add(pv);
}
profile.LastActivityDate = DateTime.UtcNow;
profile.Authenticated = isAuthenticated;
ProviderRepository.Save(ApplicationName, profile);
return svc;
}
// Writes profile property values to the data source. The values are provided by ASP.NET in a
// SettingsPropertyValueCollection. See SetPropertyValues for details.
public override void SetPropertyValues(SettingsContext context, SettingsPropertyValueCollection properties)
{
if (properties == null || properties.Count < 1 || context == null)
{
throw new ProviderException('No properties set in profile');
}
string username = (string)context['UserName'];
bool isAuthenticated = (bool)context['IsAuthenticated'];
Profile profile = ProviderRepository.GetProfileByUserName(ApplicationName, username);
if (profile == null)
{
profile = new Profile(ApplicationName, Guid.Empty, username, isAuthenticated, DateTime.UtcNow, DateTime.UtcNow);
}
foreach (SettingsPropertyValue pv in properties)
{
switch (pv.Name)
{
case 'StringProperty':
profile.StringProperty = (string)pv.PropertyValue;
break;
case 'IntProperty':
profile.Int32Property = (int)pv.PropertyValue;
break;
case 'BooleanProperty':
profile.BooleanProperty = (bool)pv.PropertyValue;
break;
case 'DateTimeProperty':
profile.DateTimeProperty = (DateTime)pv.PropertyValue;
break;
default:
throw new ProviderException('Unsupported property.');
}
}
profile.LastActivityDate = DateTime.UtcNow;
profile.LastUpdateDate = DateTime.UtcNow;
ProviderRepository.Save(ApplicationName, profile);
}
#endregion
#region - Helper Methods -
private ProfileInfo GetProfileInfoFromProfile(Profile profile)
{
DateTime nullDate = new DateTime(0);
int size = 0; // Todo: calculate the size of the profile
ProfileInfo profileInfo = new ProfileInfo(profile.UserName, profile.Anonymous, (profile.LastActivityDate == null ? nullDate : profile.LastActivityDate.Value), (profile.LastUpdateDate == null ? nullDate : profile.LastUpdateDate.Value), size);
return profileInfo;
}
#endregion
} // End Class
} // End Namespace
Now rebuild the solution. Your Report.Html file should look like the screen shot above. It should have 10 concerns, 57 contexts, and 158 specifications. All of them passing.
Commit these changes to Subversion. Open http://localhost;8080 and view the TeamCity build results.
References
- http://msdn.microsoft.com/en-us/library/aa479035.aspx
- http://msdn.microsoft.com/en-us/library/ta63b872.aspx
Previous Articles in this Series
- Part 1, Introduction
- Part 2, Version Control
- Part 3, Automated Builds
- Part 4, BDD with MSpec
- Part 5, Writing Specs
- Part 6, Writing Specs Continued
- Part 7, Custom Web Errors
- Part 8, Adding a Custom Membership Provider
- Part 9, Adding a Custom Role Provider
- Part 10, Adding a Custom Profile Provider
- Part 11, Finishing the Custom Membership Provider
- Part 12, Finishing the Custom Role Provider













Recent Comments