Search code examples
asp.net-mvc-4unity-containerravendbmvc-mini-profiler

RavenDb Mini Profiler only loads on the first page load


I'm trying the get the mini profiler for RavenDb running in my ASP.NET MVC4 project.

I have the following in my Unity bootstrapper:

[assembly: WebActivator.PreApplicationStartMethod(typeof(Web.App.App_Start.AppStart_Unity), "Start")]
public static class AppStart_Unity
{
    public static void RegisterServices(IUnityContainer container)
    {
        container.RegisterInstance(DocumentStoreFactory.Create(ConfigurationManager.ConnectionStrings[0].Name));
        container.RegisterType<IDocumentSession>(new HierarchicalLifetimeManager(), new InjectionFactory(c => c.Resolve<IDocumentStore>().OpenSession(ConfigurationManager.ConnectionStrings[0].Name)));
    }

    public static void Start()
    {
        // Create the unity container
        IUnityContainer container = new UnityContainer();

        // Register services with our Unity container
        RegisterServices(container);

        // Tell ASP.NET MVC to use our Unity DI container
        DependencyResolver.SetResolver(new UnityServiceLocator(container));

        // hook up the profiler    
        var store = container.Resolve<IDocumentStore>();
        var documentStore = store as DocumentStore;
        if (documentStore != null)
        {
            Raven.Client.MvcIntegration.RavenProfiler.InitializeFor(documentStore);
        }
    }
}

In my master _Layout I have the following:

<head>
    @Raven.Client.MvcIntegration.RavenProfiler.CurrentRequestSessions()
</head>

The first time I start up the web application I can see the profiler, no problem.

However, any subsequent page requests and the profiler is not visible.

When I look at the page source, I can see the div container is there, but unpopulated with data. No JavaScript errors at all. Very odd. The HTML rendered looks like this:

<div class="ravendb-profiler-results">
    <div id="ravendb-session-container"></div>
    <p></p>
    <a href="#" class="ravendb-toggle ravendb-close">Close</a>
</div>

Comparing the requests, I see these requests in the first load:

  1. http://localhost:62238/ravendb/profiling?path=yepnope.js
  2. http://localhost:62238/ravendb/profiling?path=jquery.tmpl.min.js
  3. http://localhost:62238/ravendb/profiling?path=ravendb-profiler-scripts.js
  4. http://localhost:62238/ravendb/profiling?path=jquery.tmpl.min.js
  5. http://localhost:62238/ravendb/profiling?path=ravendb-profiler-scripts.js
  6. http://localhost:62238/ravendb/profiling?path=Templates%2Ftotals.tmpl.html
  7. http://localhost:62238/ravendb/profiling?path=Templates%2Fravendb-profiler.tmpl.html
  8. http://localhost:62238/ravendb/profiling?path=Templates%2Fsession-template.tmpl.html
  9. http://localhost:62238/ravendb/profiling?path=Templates%2Frequest-details.tmpl.html
  10. http://localhost:62238/ravendb/profiling?id%5B%5D=d3ada4e4-4bc3-4a7c-bd36-64cc8017d94a
  11. http://localhost:62238/ravendb/profiling?path=styles.css

In subsequent loads, I see the following requests:

  1. http://localhost:62238/ravendb/profiling?path=yepnope.js
  2. http://localhost:62238/ravendb/profiling?path=jquery.tmpl.min.js
  3. http://localhost:62238/ravendb/profiling?path=ravendb-profiler-scripts.js
  4. http://localhost:62238/ravendb/profiling?path=jquery.tmpl.min.js
  5. http://localhost:62238/ravendb/profiling?path=ravendb-profiler-scripts.js

Oddly, I'm seeing duplicated calls in both cases for jquery.tmpl.min.js and ravendb-profiler-scripts.js.

The ravendb-profiler-scripts.js contains the line:

 9. var load = function () {
10. if (options.id.length == 0)
11.    return;

In the subsequent loads, options.id.length is zero. The templates then don't load, and the results are not fetched.

The first page load contains the script:

<script type="text/javascript">
yepnope([{ test: window.jQuery, nope: '/ravendb/profiling?path=jquery-1.6.1.min.js' }, { test: window.jQuery && window.jQuery.fn.tmpl, nope: '/ravendb/profiling?path=jquery.tmpl.min.js' }, {load: '/ravendb/profiling?path=ravendb-profiler-scripts.js', complete: function() { jQuery(function() { RavenDBProfiler.initalize({ id:['df05238a-24a6-4a16-ad63-3b9537e9b544'], url: '/ravendb/profiling' }); }) } }]);
</script>

The subsequent loads contain:

<script type="text/javascript">
yepnope([{ test: window.jQuery, nope: '/ravendb/profiling?path=jquery-1.6.1.min.js' }, { test: window.jQuery && window.jQuery.fn.tmpl, nope: '/ravendb/profiling?path=jquery.tmpl.min.js' }, {load: '/ravendb/profiling?path=ravendb-profiler-scripts.js', complete: function() { jQuery(function() { RavenDBProfiler.initalize({ id:[], url: '/ravendb/profiling' }); }) } }]);
</script>

Note the lack of id objects.

I've also tried the mini-profiler and I have also tried rolling back from the latest unstable RavenDb client to the current stable release. Nothing appears to make a difference.

Is this the expected behavior? Do I need to do anything else? Am I being an idiot here?

Update

I've just installed the Glimpse.Ravendb plugin and it reports:

Profiling is currently not supported for EmbeddableDocumentStore.

However, I'm clearly not using the EmbeddableDocumentStore:

public static class DocumentStoreFactory
{
    public static IDocumentStore Create(string connectionStringName)
    {
        var documentStore = new DocumentStore { ConnectionStringName = connectionStringName };
        documentStore.Initialize();
        documentStore.DatabaseCommands.EnsureDatabaseExists(connectionStringName);

        var catalog = new CompositionContainer(new AssemblyCatalog(typeof(Users_ByKarmaAndLocation).Assembly));
        IndexCreation.CreateIndexes(catalog, documentStore.DatabaseCommands.ForDatabase(connectionStringName), documentStore.Conventions);

        return documentStore;
    }
}

I'm not sure if this is a red herring or not. Thought I would mention it though.


Solution

  • The problem was my Unity setup. I should not have used a Unity HierarchicalLifetimeManager() but a PerResolveLifetimeManager(). The Glimpse problem resolved once I had restarted the application.

    With hindsight, I should have paid closer attention to the different types of LifetimeContainers and used them properly.

    The updated Unity config looks like this:

    public static class AppStart_Unity
    {
        public static void RegisterServices(IUnityContainer container)
        {
            container.RegisterInstance(DocumentStoreFactory.Create(ConfigurationManager.ConnectionStrings[0].Name));
            //container.RegisterType<IDocumentSession>(new HierarchicalLifetimeManager(), new InjectionFactory(c => c.Resolve<IDocumentStore>().OpenSession(ConfigurationManager.ConnectionStrings[0].Name)));
            container.RegisterType<IDocumentSession>(new PerResolveLifetimeManager(), new InjectionFactory(c => c.Resolve<IDocumentStore>().OpenSession()));
        }
    
        public static void Start()
        {
            // Create the unity container
            IUnityContainer container = new UnityContainer();
    
            // Register services with our Unity container
            RegisterServices(container);
    
            // Tell ASP.NET MVC to use our Unity DI container
            DependencyResolver.SetResolver(new UnityServiceLocator(container));
    
            var store = container.Resolve<IDocumentStore>();
            var documentStore = store as DocumentStore;
            if (documentStore == null)
            {
                return;
            }
    
            RavenProfiler.InitializeFor(
                documentStore,
                "Email", "HashedPassword", "AkismetKey", "PasswordSalt", "UserHostAddress");
            Profiler.AttachTo(documentStore);
        }
    }