Subscribe to my blog

RavenDB - The Image Gallery Project (XI) - Our First View

Published on 2010-10-14

The code for this and all other entries in this series can be found here: http://github.com/robashton/RavenGallery/

So far we’ve concentrated on writing to RavenDB via our entities. Traditionally although it has been frowned on (especially of late), when constructing view models with an ORM like NHibernate, it has been common practise to pull the entities/POCOS from the repositories, and either include them directly on the ViewModel or project them onto a custom view model.

The more savvy users would go a step further and perform queries against the object model and with a minimal number of database queries pull back just the data that they need for the view model, and for even , or in some cases they may well write code which pre-creates these view models so getting a view out is a very simple query – this can be a lot of work though.

We can strike a balance in RavenDB at the more elegant end of this spectrum by creating indexes against the stored documents and querying those to get the data out that is required. This can be as simple as executing a dynamic query against the document store (ala what we’ve seen so far in registration/authentication) or as complicated as pre-defining indexes as part of the application code base. I’ll explain a bit more about that

Defining the view

We’ll start with the basics first, as I haven’t fully explained how I’m currently getting to my view layer, first off, I decide what data I want to be able to browse/filter/sort on in my basic view, in order to keep things simple my only input for now will be the paging information required to browse through the images effectively. Here is the class that we’ll use for input into our view factory.

    public class ImageBrowseInputModel
    {
        public int Page { get; set; }
        public int PageSize { get; set; }
    }

And of course the view that we’re going to create

    public class ImageBrowseView
    {
        public int PageSize
        {
            get;
            private set;
        }
 
        public int Page
        {
            get;
            private set;
        }
 
        public IEnumerable<ImageBrowseItem> Items
        {
            get;
            private set;
        }
 
        public ImageBrowseView(int page, int pageSize, IEnumerable<ImageBrowseItem> items)
        {
            this.Page = page;
            this.PageSize = PageSize;
            this.Items = items;
        }
    }

And the items on that view

    public class ImageBrowseItem
    {
        public string Title
        {
            get;
            private set;
        }
 
        public string Filename
        {
            get;
            private set;
        }
 
        public ImageBrowseItem(string title, string filename)
        {
            this.Title = title;
            this.Filename = filename;
        }
    }

Of note here, is that the actual items included on the main model don’t contain all of the information contained within the document, just the data that we need to display on the browsing page.

I then define an instance of the relevant view factory that can take this in and use it to generate the appropriate view “somehow”

    public class ImageBrowseViewFactory : IViewFactory<ImageBrowseInputModel, ImageBrowseView>
    {
        private IDocumentSession documentSession;
 
        public ImageBrowseViewFactory(IDocumentSession documentSession)
        {
            this.documentSession = documentSession;
        }
        public ImageBrowseView Load(ImageBrowseInputModel input)
        {
            throw new NotImplementedException();
        }
    }

Rather than inject a repository into this factory and do a query on the entities and flattening their data across the view, the IDocumentSession is injected directly into the factory so we can attempt to get only the information we need, in the most direct way possible.

Obviously this requires some tests, but as those tests are a little bit verbose you can just go and look at them on Github!

        public ImageBrowseView Load(ImageBrowseInputModel input)
        {
            // Adjust the model appropriately
            input.PageSize = input.PageSize == 0 || input.PageSize > 20 ? 20 : input.PageSize;
 
            var items = documentSession.Query<ImageDocument>()
                .Skip(input.Page * input.PageSize)
                .Take(input.PageSize)
                .ToArray()
                .Select(x => new ImageBrowseItem(x.Title, x.Filename));
               
            return new ImageBrowseView(
                input.Page,
                input.PageSize,
                items);
        }

There, that’s all there is to it, this will give us a paged list of ImageDocuments from RavenDB and project that into the view we wish to return.

So surely that’s done then?

This is sub-par for several reasons, the two most important ones are

In the next entries we’ll be looking at the different ways of pulling this information out, and how this view is used within our ASP.NET MVC View

blog comments powered by Disqus