Over a million developers have joined DZone.

NancyFx: Live editable views with RavenDB

DZone's Guide to

NancyFx: Live editable views with RavenDB

· Database Zone ·
Free Resource

Built by the engineers behind Netezza and the technology behind Amazon Redshift, AnzoGraph is a native, Massively Parallel Processing (MPP) distributed Graph OLAP (GOLAP) database that executes queries more than 100x faster than other vendors.  

When building a website with NancyFX by default views are loaded from the file system - pretty much like with all MVC-based websites. While NancyFX also supports loading views embedded in assemblies as resources , both options require re-deploying of actual files when something in the view needs updating. Even with fully CI environments, that is still sort of a PITA.

Here is how to use RavenDB to override views in a live website without re-deploying anything. Basically what this does, thanks to NancyFX's modular and flexible design, is take the default ViewLocationProvider and encapsulate it, reading all the views from the original location (file system or assembly resources), and give precedence to views loaded from RavenDB.

The code featured here makes 2 assumptions:

1. A document name convention for view documents is preserved - basically some prefix (for example "MyWebsite/") used to prevent polluting the document store and then the full view name (location + name + extension). When loading all available views, we use a filter to make sure we load only views with a supported extension (determined by the installee view-engines). A view-template document in RavenDB will then have an ID similar to "WebsiteViews/Views/Home/Read.cshtml".

2. There are less than 1024 views stored to RavenDB. This is probably safe to assume, or you have some monstrous website.

There's one bit missing here - view-cache invalidation. By default NancyFx will cache all views it loaded indefinitely, as far as I can tell. That's bad for us, because when you update a template in your RavenDB store you do want to invalidate all caches, or at least one specific template you updated. This is something I'll keep for another post.

This is the custom ViewLocationProvider class:

using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using NSemble.Core.Models;
using Nancy;
using Nancy.ViewEngines;
namespace NSemble.Core.Nancy
    public class RavenViewLocationProvider : IViewLocationProvider
        private readonly IViewLocationProvider defaultViewLocationProvider;
        public RavenViewLocationProvider(IRootPathProvider rootPathProvider)
            defaultViewLocationProvider = new FileSystemViewLocationProvider(rootPathProvider);
        public RavenViewLocationProvider(IRootPathProvider rootPathProvider, IFileSystemReader fileSystemReader)
            defaultViewLocationProvider = new FileSystemViewLocationProvider(rootPathProvider, fileSystemReader);
        public IEnumerable<ViewLocationResult> GetLocatedViews(IEnumerable<string> supportedViewExtensions)
            var sb = new StringBuilder();
            // Make sure to only load saved views with supported extensions
            foreach (var s in supportedViewExtensions)
                if (sb.Length > 0)
            ViewTemplate[] views = null;
            using (var session = NSembleModule.DocumentStore.OpenSession())
                // It's probably safe to assume we will have no more than 1024 views, so no reason to bother with paging
                views = session.Advanced.LoadStartingWith<ViewTemplate>(Constants.RavenViewDocumentPrefix, sb.ToString(), 0, 1024);
            // Read the views from the default location
            IEnumerable<ViewLocationResult> defaultViews = defaultViewLocationProvider.GetLocatedViews(supportedViewExtensions);
            if (views.Length == 0)
                return defaultViews;
            var ret = new HashSet<ViewLocationResult>(from v in views
                                  where supportedViewExtensions.Contains(v.Extension)
                                                      select new ViewLocationResult(
                                                          () => new StringReader(v.Contents)));
            foreach (var v in defaultViews)
            return ret;

You will need to register it in your Nancy Boostrapper class:

protected override NancyInternalConfiguration InternalConfiguration
return NancyInternalConfiguration
    .WithOverrides(x => x.ViewLocationProvider = typeof (RavenViewLocationProvider))
            .WithIgnoredAssembly(asm => asm.FullName.StartsWith("RavenDB", StringComparison.InvariantCulture)); // or override ConfigureApplicationContainer to set AutoRegister to false


Download AnzoGraph now and find out for yourself why it is acknowledged as the most complete all-in-one data warehouse for BI style and graph analytics.  


Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}