RavenDB - The Image Gallery Project (XII) - Integrating our view with ASP.NET MVC

Published on 2010-10-17

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

Before improving the view, we’ll first just make sure everything works as planned by displaying a list of images on a page, I’ll not bore with the tests (although I can assure you that they exist)

Here is my controller action

        public ActionResult Browse(ImageBrowseInputModel input)
        {
            var model = viewRepository.Load<ImageBrowseInputModel, ImageBrowseView>(input);
            return View(model);
        }

The default model binder will take in parameters from the query string (in this case, pagesize and page), populate the model and pass it into the action. We could perform some validation on it in a validator and reject it, or we can do some sanity checking in the view factory and override any dodgy values (I plump for the latter, although there is no reason why we couldn’t combine the two).

My design skills are non-existent, so my view is very simple

    <h2>Browse Images</h2>
    <p>Page <%: Model.Page %>, showing <%: Model.PageSize %> items per page</p>
    
    <div class="image-browser">
        <%foreach(var item in Model.Items){ %>
        <div class="browsing-image">
                <h4><%: item.Title %></h4>
                 <img src="<%= this.ResolveUrl(String.Format("/Resources/Image/{0}", Url.Encode(item.Filename))) %>" />
        </div>
        <%} %>
    </div>

I’m pointing all the image endpoints at an action which is going to fetch that image from storage for us and return with the appropriate mime-type.

Note: Pulling lots of attachments from RavenDB this way is probably not recommended if you want a site that scales and performs well, there will most likely be a refactor job as a later part in the series demoing how we might migrate from this system to another.

This is the action, and as you can see I’ve added another method to the file storage service (because I now need it, I don’t write code until I need it)

        public ActionResult Image(string filename)
        {
            Byte[] fileBytes = fileStorageService.RetrieveFile(filename);
            return File(fileBytes, "image/jpeg");           
        }

Writing a test in the same vein as the previous file command code, we end up with

        [Test]
        public void WhenRetrieveFileInvokedWithValidArguments_AttachmentIsReturnedFromRaven()
        {
            Byte[] fileBytes = new Byte[] { 3, 1, 4, 1, 5, 9 };
            String filename = "images/mySuperDuperFile";
 
            this.Store.DatabaseCommands.PutAttachment(filename, null, fileBytes, new Newtonsoft.Json.Linq.JObject());
 
            RavenFileStorageService storage = new RavenFileStorageService(this.Store);
            var retrievedAttachment = storage.RetrieveFile(filename);
            Assert.AreEqual(fileBytes, retrievedAttachment);
        }

and

        public byte[] RetrieveFile(string filename)
        {
            var file = documentStore.DatabaseCommands.GetAttachment(filename);
            return file != null ? file.Data : null;
        }

 

The output of that gives us something that looks like this.

image

 

Note the query string parameters which are automatically being bound to the InputModel with very little code we’ve ended up with a very rudimentary image gallery where we can register/logon/upload images/browse images. From this point on we’ll be looking at ways to improve what we have in terms of performance, best practises and perhaps reversing some of our earlier design decisions if they prove to be untenable. (Always guided by tests though).

Oh, and adding some functionality and showing off various features in RavenDB to make your life easy, that’s the purpose of this blog series after all.

2020 © Rob Ashton. ALL Rights Reserved.