Search code examples
cookiesrolesmembershiproleprovider

ASP.NET Universal Providers - Roleprovider does not cache roles in cookie


Ironically my role provider does not cache the roles in a cookie anymore. That was working earlier. Unfortunately i have noticed that only now, so i cannot say what causes the problem. But i think it has to do with the update to the new version 1.2 of the universal providers (released on 16th august).

My config for the roleprovider looks like:

 <roleManager enabled="true" cacheRolesInCookie="true" cookieName="X_Roles" 
cookiePath="/" cookieProtection="All" cookieRequireSSL="true" cookieSlidingExpiration="true" cookieTimeout="1440" 
createPersistentCookie="false" domain="" maxCachedResults="25" defaultProvider="XManager_RoleProvider">
<providers>
<clear/>
<add name="XManager_RoleProvider" type="ManagersX.XManager_RoleProvider, AssemblyX" 
connectionStringName="XEntities" applicationName="/" rolesTableName="Roles" roleMembershipsTableName="Users_Roles"/>
</providers>
</roleManager>

Everything is working fine with the rolemanager (loginviews, menu with sitemaptrimming etc.), but it is only not caching the roles anymore. The membership provider, sessionstate etc. are also working fine and the cookies of them are set correctly.

All properties of the static Roles-class are correctly set and everything in Httpcontext (IsSecureConnection etc.) is also correct.

The roles cookie was set earlier, but not anymore. I hope anybody can help me with my problem.

Thanks in advance.

Best Regards,

HeManNew

UPDATE: Has nobody got the same problem or a tip for me, please?


Solution

  • Below are the details of the Custom Role Provider I wrote that uses proper caching and doesn't hit the database on each page load.

    ============= My Code-Behind file ===============

    using System;
    using System.Collections.Generic;
    using System.Collections.Specialized;
    using System.Configuration;
    using System.Data;
    using System.Data.SqlClient;
    using System.Linq;
    using System.Web;
    using System.Web.Caching;
    using System.Web.Security;
    
    namespace MyProject.Providers
    {
        public class CustomRoleProvider : RoleProvider
        {
            #region Properties
    
            private static readonly object LockObject = new object();
            private int _cacheTimeoutInMinutes = 0;
    
            #endregion
    
            #region Overrides of RoleProvider
    
            public override void Initialize(string name, NameValueCollection config)
            {
                // Set Properties
                ApplicationName = config["applicationName"];
                _cacheTimeoutInMinutes = Convert.ToInt32(config["cacheTimeoutInMinutes"]);
    
                // Call base method
                base.Initialize(name, config);
            }
    
            /// <summary>
            /// Gets a value indicating whether the specified user is in the specified role for the configured applicationName.
            /// </summary>
            /// <returns>
            /// true if the specified user is in the specified role for the configured applicationName; otherwise, false.
            /// </returns>
            /// <param name="username">The user name to search for.</param><param name="roleName">The role to search in.</param>
            public override bool IsUserInRole(string username, string roleName)
            {
                // Get Roles
                var userRoles = GetRolesForUser(username);
    
                // Return if exists
                return userRoles.Contains(roleName);
            }
    
            /// <summary>
            /// Gets a list of the roles that a specified user is in for the configured applicationName.
            /// </summary>
            /// <returns>
            /// A string array containing the names of all the roles that the specified user is in for the configured applicationName.
            /// </returns>
            /// <param name="username">The user to return a list of roles for.</param>
            public override string[] GetRolesForUser(string username)
            {
                // Return if User is not authenticated
                if (!HttpContext.Current.User.Identity.IsAuthenticated) return null;
    
                // Return if present in Cache
                var cacheKey = string.format("UserRoles_{0}", username);
                if (HttpRuntime.Cache[cacheKey] != null) return (string[]) HttpRuntime.Cache[cacheKey];
    
                // Vars
                var userRoles = new List<string>();
                var sqlParams = new List<SqlParameter>
                                    {
                                        new SqlParameter("@ApplicationName", ApplicationName),
                                        new SqlParameter("@UserName", username)
                                    };
    
                lock (LockObject)
                {
                    // Run Stored Proc << Replace this block with your own Database Call Methods >>
                    using (IDataReader dr =
                        BaseDatabase.ExecuteDataReader("aspnet_UsersInRoles_GetRolesForUser", sqlParams.ToArray(),
                                                       Constants.DatabaseConnectionName) as SqlDataReader)
                    {
                        while (dr.Read())
                        {
                            userRoles.Add(dr["RoleName"].ToString());
                        }
                    }
                }
    
                // Store in Cache and expire after set minutes
                HttpRuntime.Cache.Insert(cacheKey, userRoles.ToArray(), null,
                                         DateTime.Now.AddMinutes(_cacheTimeoutInMinutes), Cache.NoSlidingExpiration);
    
                // Return
                return userRoles.ToArray();
            }
    
            /// <summary>
            /// Gets or sets the name of the application to store and retrieve role information for.
            /// </summary>
            /// <returns>
            /// The name of the application to store and retrieve role information for.
            /// </returns>
            public override sealed string ApplicationName { get; set; }
    
            // I skipped the other methods as they do not apply to this scenario
    
            #endregion
        }
    }
    

    ============= End of My Code-Behind file ===============

    ============= My Web.Config file =======================

    <roleManager enabled="true" defaultProvider="CustomRoleManager">
      <providers>
        <clear />
        <add name="SqlRoleManager" type="System.Web.Security.SqlRoleProvider" connectionStringName="AspnetDbConnection" applicationName="MyApplication"/>
        <add name="CustomRoleManager" type="MyProject.Providers.CustomRoleProvider" connectionStringName="AspnetDbConnection" applicationName="MyApplication" cacheTimeoutInMinutes="30" />
      </providers>
    </roleManager>
    

    ============= End of My Web.Config file ================

    The cache is set to expire automatically after every 30 minutes. You can modify this as you deem fit.

    Cheers.