Archive for the 'c#' Category

IE 9 AJAX request caching (MVC)

So IE9 is greedy when it comes to caching and automatically caches AJAX requests

This was an issue on an app that I’ve been working on that uses a lot of AJAX. IE9 was caching the AJAX requests and causing some problems downstream.

This can be stopped client side by setting cache to false in the JQuery ajaxSetup

$(document).ready(function() {
$.ajaxSetup({ cache: false });
});

However, I wanted to implement somthing server side, so that IE9 won’t cache any AJAX requests.

To do this I wrote an AjaxCacheControlAttribute that sniffs for AJAX requests and sets the relevant caching properites to prevent caching. To implement this across the app I then registered this in the GlobalFiltersCollection.

The attribute

public class AjaxCacheControlAttribute: ActionFilterAttribute
{
   public override void OnResultExecuted(ResultExecutedContext filterContext)
   {
       if (filterContext.RequestContext.HttpContext.Request.IsAjaxRequest())
       {
          filterContext.HttpContext.Response.Cache.SetExpires(DateTime.UtcNow.AddDays(-1));
          filterContext.HttpContext.Response.Cache.SetValidUntilExpires(false);
          filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
          filterContext.HttpContext.Response.Cache.SetNoStore();
       }
    }
}

MVC – Getting User Roles From Multiple Sources (register and resolve arrays of dependencis using the fluent api)

(This post also appear in our team blog DotScrapBook)

In the last post I talked about encapsulating the authorisation and user credentials (i.e IPrincipal) logic in a separate, re-usable DLL (known as AuthServices).

Part 1 of that post discussed the DLL contents in detail. Part 2 focused upon using that DLL in an MVC application.

This post follows up on “Part 2″ specifically adding a user’s roles to the UserData objet prior to serialisation, on-route to becoming the auth cookie.

The code sample that I gave for using the AuthServices DLL is repeated below:

_authenticationService.Authenticate(userNameString, password);
if (_authenticationService.Result.Authenticated)
{
       _currentUserData = _authenticationService.Result.CurrentUserData;
       _currentUserData.Roles = GetRolesForUser(userName);//THE SUBJECT OF THIS POST
       _cookieManager.CreateUserCookie(userName, _currentUserData);
}

This post explores in more detail what lies behind the GetRolesForUser(string userName) method and how this can utilise more than one provider of roles.

Why bother?

The organisation in which I work is big. We have thousands of staff and many thousands more students. Applications written for an organisation of this size usually need to access different sources of data to provide a user’s roles relevant to the specific application. In projects like this you can’t easily use the standard RoleProvider stuff in a config file.

The Answer – Multiple Role Providers

To implement multiple roles I inject (in an IOC stylee) into my login service the interface IRolesMgr. IRolesMgr exposes the following:

public interface IRolesMgr
    {
        List GetAllRolesForUser(string userName);
    }

The interesting part is in the constructor of the implementation.

public class RolesMgr: IRolesMgr
    {
        private IRoleMgrComponent[] _roleManagers;

        public RolesMgr(IRoleMgrComponent[] roleManagers)
        {
            _roleManagers = roleManagers;
        }

        public List GetAllRolesForUser(string userName)
        {
            List roles = new List();
            foreach (var mgr in _roleManagers)
            {
                roles.AddRange(mgr.GetRolesForUser(userName));
            }
        }
    }

As can be seen the constructor has a dependency on an array of IRoleMgrComponents each of which will contain the access logic needed to identify a user’s roles from a different source.
Each IRoleMgrComponent implements the following:

public interface IRoleMgrComponent
    {
        List GetRolesForUser(string userName);
    }

That’s all very good, but the trick is getting the IOC container, in this case, Castle Windsor, to instantiate the appropriate implementations of IRoleMgrComponent in the roleManagers array.

This is done in the Component Registrar class used to register components to Castle by using the “ServiceOveride” method (more details of this can be seen on Mike Hadlow’s post – which was the original inspiration for the castle registration code – thanks Mike!). In effect this allows you to register and resolve arrays of dependencis using the fluent api.

container.Register(
                Component.For()
                    .ImplementedBy()
                    .ServiceOverrides(
                        ServiceOverride.ForKey("roleManagers").Eq(
                            "HumsAuthDbRoleManager",
                            "StudentAuthRoleMgr"
                        )
                    ),
                AllTypes
                    .FromAssemblyNamed("ApplicationServices")
                    .BasedOn()
                        .WithService.FromInterface(typeof(IRoleMgrComponent))
                        .Configure(c => c.Named(c.Implementation.Name))
                );

Once you have overriden this specific component you can continue to register all the other components in that assembly in the normal way, say:
container.Register(
                AllTypes.Pick()
                .FromAssemblyNamed("ApplicationServices")
                .WithService.FirstInterface());

Conclusion

Implementing RolesMgr(IRoleMgrComponent[]) in conjunction with the AuthServices assembly talked about in the last post, means that for any given new project I will only have to write minimal code yet benefit from User Credential information that:
a) Has the execution logic encapsulated in an (extensible) AuthServices library
b) Can uitilise dependency injection to configure how where and how the roles data comes from in the credential information.

S#harp Architecture – Testing multiple database mappings in MappingIntegrationTests

I’m using s#harp for a project that needs to map multiple db’s. Whilst this process of setting this up is well documented on the wiki (http://wiki.sharparchitecture.net/FAQ.ashx) the process of getting mutli db mappings to pass the MappingIntegrationTests isn’t.
For what it’s worth I’ve hacked together a means to test that each Fluent mapping is tested to see if it matches one of the db’s. It aint pretty but it does smoke out dodgy mappings.
——————————————————-
//Add a list that holds the session keys
private List<string> sessionKeys;
[SetUp]
public virtual void SetUp()
{
    string[] mappingAssemblies = RepositoryTestsHelper.GetMappingAssemblies();
    configuration = NHibernateSession.Init(new SimpleSessionStorage(), mappingAssemblies,
    new AutoPersistenceModelGenerator().Generate(),
    "../../../../app/Humanities.IBusiness.Web/NHibernate.config");
/* ADD EXTRA DB'S TO SESSION CONFIG  */
    var configuration2 = NHibernateSession.AddConfiguration(DataGlobals.ROLES_DB_FACTORY_KEY,
    mappingAssemblies,
    new AutoPersistenceModelGenerator().Generate(),
        "../../../../app/Humanities.IBusiness.Web/NHibernateForRolesDb.config",null,null, null);
/* ADD EACH SESSION KEY TO LIST */
    sessionKeys = new List<string>();
    sessionKeys.Add(DataGlobals.DEFAULT_DB_KEY);
    sessionKeys.Add(DataGlobals.ROLES_DB_FACTORY_KEY);
}

[Test]

public void CanConfirmDatabaseMatchesMappings()
{
//GET ALL META DATA FROM SESSION (NOTE DOESN@T MATTER WHICH SESSION FACTORY IS USED!
    var allClassMetadata = NHibernateSession.GetDefaultSessionFactory().GetAllClassMetadata();
    if (NHibernateSession.IsConfiguredForMultipleDatabases())
    {
    //INTEROGATE EACH CLASS
        foreach (var entry in allClassMetadata)
        {
            bool found = false;
            //ENSURE EACH CLASS MAPS TO A DB
            foreach (string key in sessionKeys)
           {
                ISession session = NHibernateSession.CurrentFor(key);
                try
                {
                    session.CreateCriteria(entry.Value.GetMappedClass(EntityMode.Poco))
                    .SetMaxResults(0).List();
                    found = true;
                }
                catch (Exception ex) { }
            }
        if (found == false)
            throw new MappingException("Mapping not found for " + entry.Key.ToString());
    }
}

else //Do what you'd normally do or do the above...


Topics/ Categories

My (Live) Twitter stream

Archives

My Recent Bookmarks

 

February 2012
M T W T F S S
« Oct    
 12345
6789101112
13141516171819
20212223242526
272829  

Follow

Get every new post delivered to your Inbox.