Monday, 9 June 2014

Internal project, MVC site done


I'm now done on putting together the mvc site for the internal project.

A few screenshots of what it looks like now:

Home, not logged in

New Status

History



Search

The very visible bar across the bottom of the screen is Glimpse, which is an awesome tool to give you a window into what is happening on your server.

I learned a few interesting things while working through this.

Data

It's interesting to consider that I've ended up so many data objects to represent similar data. This is mostly due to providing different abstraction layers.

Consider the data to represent a status post. I've got the following:
  1. EEF data model object, which represents exactly what the table represents
  2. The data model that is returned from the repository, this is different from the EF data model to enable adding a different backend (DataInterfaces.Models.Status)
  3. The ViewModel displayed by the site (Site.Models.Status), which is optimised for display. 

On reflection I could have added more view models. For example, the history view has the following rather unpleasant piece of code:
 @Html.Partial("~/Views/PartialViews/Pagination.cshtml", new Site.Models.Pagination { PageCount = Model.PageCount, Page = Model.Page, BaseUrl = "/Status?" });  

This could be far neater if I'd simply added an instances of the Pagination object on the ViewModel on the StatusList object. However I wanted to re-use the models that the site used for the WebApi interface and this felt like a reasonable compromise.

Unit testing controllers

I tried to keep as much of the code out of the controllers (following best principles), but I did want to unit test the code I had there.

This ended up being a bit more work than expected. I had a dependency on session state and it took a little while to work out how best way to make this testable. The obvious solution was to wrap the session object in another object. However that felt rather like a reinventing the wheel. Surely there was a better way.

After some judicious googling, I found that the object I was looking for were HttpSessionStateBase and HttpSessionStateWrapper. When using Ninject as an IoC container, the binding for this was:

 kernel.Bind<HttpSessionStateBase>().ToConstructor<HttpSessionStateWrapper>(x => new HttpSessionStateWrapper(HttpContext.Current.Session));  

I also needed to retrieve the user's ip address to track view counts and like counts. These followed the same basic patterns, the objects were HttpRequestBase and HttpRequestWrapper.

It was nice to find something that was well thought out.

Misc

Ninject is awesome as always, although I always seem to forget the binding syntax, resorting to this awesome cheatsheet.

I added log4net, just because it wouldn't be a real site without some logging.

Css is mostly vanilla bootstrap. I probably could have done more with this, but I could have kept working on this forever. Sooner or later you have to draw a line.

Current status

It's been really interesting working on this. I'm finding that trying to implement something real forces you to make trade offs and to understand the technology better. I worked with all these technologies a fair bit, but it is still possible to find something that a bit new, for example testing session state in the controller.

I'm shifting the order in what I'm going to work on this a little.
  1. Document the UI - I've found this tends to make the implementation clearer
  2. Implement in bootstrap, MVC4 with SQL Server backend
  3. Design JSON API to access app
  4. Implement JSON api using WebApi backend
  5. Replace MVC app with javascript client side framework, angular
  6. Swap the SQL Server backend for a No SQL database
  7. Replace the WebApi backend with an F# implementation
  8. Replace the WebApi backend with node.js



No comments:

Post a Comment