Internal Project – implement the API

I’ve completed the work in implementing the API.

This was surprisingly more complex than expected. I’ve spent a bit of time working with WebApi and I’d also done the work to design the API, but I still ran into a few unexpected issues, some of which required me to change the design of the API.

Finding the IP address

For some reason I’d decided to include logging the IP address of the client machine when people mark a status as liked and when a status is marked as viewed. This proved to be a bit harder than expected. After poking around in the Request object for a while, I resorted to google, which led to this stack overflow question.

Routing Fun

When I’d designed the API, I’d had planned GET requests to cover retrieving a single status, searching for statuses and retrieving the status history, all hitting the same URL. I’d slightly naively assumed that this would be handled something like function overloading. I’d also confused this with the simple case where you return all and retrieve a single item by id. In that case, this is handled by routing.
Clearly this doesn’t work, how would the server resolve the HTTP verb to a single function?
As a result I needed to move this to separate the methods using routing. This meant that search became: /status/search as a GET.

Retrieving values passed in

I ran into a few problems trying to retrieve values passed to the server. Should they go in the body? URL? Headers?

In retrospect, probably the best place for the session id would have been as a header. Ideally the authentication for this could be handled as less of a copy and paste implementation. It would be a bit overkill in the current situation though.

Progress

  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

Internal project – design the API

I’ve spent some time designing the API for my internal project.

I’ve documented the design of the API here.

Key Points

Session 

Following best practices, I’ve avoided including the login and password with each request. Instead there is a session service. Call this service to create a new session and get a session token in response. In addition I’ve included a method to end the session early. The intention that the session token would expire. Making a call to any of the methods on the API would reset the timeout.

HTTP

As far as possible I’ve mapped this to valid HTTP verbs.

Difficulties

One difficulty I ran into was how to provide a nice mechanism to mark a post a liked. It didn’t make sense to mark a status item as liked by making a PUT request with the entire status item. The best option was to add a status/like URL, under the status URL.

Resources

There are a sack of really good resources out there for this:

  1. Best Practices for Designing a Pragmatic RESTful API: http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api
  2. The Good, the Bad, and the Ugly of REST APIs: http://broadcast.oreilly.com/2011/06/the-good-the-bad-the-ugly-of-rest-apis.html
  3. OWASP REST Security Cheat Sheet: https://www.owasp.org/index.php/REST_Security_Cheat_Sheet

Current Status

  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

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().ToConstructor(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

Internal project – step 2 in progress

After a bit of a hiatus, I’ve returned to working on my internal project:

I’ve partially completed my initial planned step 2. I ended up spending a lot of time on setup activities, ie yak shaving. I’ve been trying to restrain myself, but it is hard.
Some of the yak shaving activities:
  1. Worrying about the structure of the project and which directory things belong in.
  2. Setup for a dev machine, in this case powershell scripts to create a database and some initial base data. I managed to avoid putting together deployment tools, but I have ended up with scripts to create the database.
  3. Implementing authentication by hand rather than just using something off the shelf. This was truly a bad idea, but by the time I’d realised it, I was already too far down the rabbit hole.
  4. Using a more secure hashing algorithm. While it was interesting to use BCrypt, it wasn’t really necessary.
However I did find something fairly interesting things during this process.

Future plans impact structure now

I was planning to swap out the backend for a nosql database. The aim was for this change to be seamless. However the structures that you might use in a relational database would be different to a nosql database.

So the Sql tables look like this:

  1. status (status_id, message, date, user_id…)
  2. status_view (status_id, date…)
  3. status_like (status_id, date…)
However for a nosql or document oriented database, it would make far more sense to have a single document represent each post, including all the data associated with the post.
This has a direct impact on how the code needs to be structured to support this. Rather than having a repository for each table, it needs to have a single repository interface to cover all of the interactions with status, ie something like this:

Structure

I took the time to split the code up between a number of projects in order to isolate the projects by functional area. I’ve currently got:
  1. DataInterfaces – models and interfaces for accessing any data
  2. DataSql – the sql implementation of the interfaces in DataInterfaces
  3. SiteLogic – the business logic for the application, all code here should be completely unit testable
  4. SiteLogic.NUnit – unit tests for the library
  5. Site – the MVC site
  6. Site.NUnit – the unit tests for the MVC site.

Testing

As far as possible I’ve been wanting to write unit tests for all of the code. Obviously this isn’t possible all the time, for example I gave up on unit testing the controller for authentication. 

Internal project – Architecture

I’m rather fond of Military history and one of the quotes that I like is:
Plans are nothing. Planning is everything. Dwight D Eisenhower

I realised I missed a step in my original plan for the project: planning. The reason I like this quote is that it is clear that the plan might not be followed, however the process of planning forces you to think about what you want to do.

So I’ve done some initial planning around this. Since I’m reading a book on documenting software architecture, I’ve dug into that for the most appropriate view to use.

Layered Architecture

Some notes on this:

  1. I want to clearly separate the UI layer from the business layer in order to facilitate adding an API
  2. The data access layer might be swapped out with a completely different data backend in the future, so that needs to be separated out. I’m currently thinking that I’ll implement these Entity Framework for the first version. I’ll avoid generic repositories to create a clean interface that doesn’t require implementing a LINQ interface over a NoSql database that might not cleanly support it.
  3. I want the Authentication to be clearly separate from the business layer in order to keep this as dependancy free as possible. This tends to be a rather complex area that is well worth ensuring it doesn’t have any dependencies.
  4. Cross cutting concerns like logging aren’t covered in this diagram

Internal Project – Step 1 – Document the UI

I’ve started putting together the UI for my home project.

You can see this in all it’s glory at https://github.com/dcamdupe/status.

Here is a sneak peek:

Home page version 1
Home page version 2
These high quality wireframes help illustrate a number of things:
  1. I don’t have access to appropriate tools at home. Rather than buying them, I’m using the highly technical approach of pen + paper + iPhone camera to capture my wireframes
  2. My hand writing is frighteningly messy
  3. In version 2 I’ve avoided the traditional wooden table for a far more attractive red table cloth with stars
For version 2 of the wireframes, I’ve tightened things up a little and used more consistent UI elements. This might not be apparent, given my limited ability with a pen. I also noticed I missed a page and a few other major elements on the pages.
I’m skipping a few normal user lifecycle elements (forgotten password etc) for simplicity’s sake.
The only thing that might not make immediate sense is the popularity box. This will be some sort of synthesis of the number of views and likes to provide an overall popularity. This could be represented by a number, an image or just a colour.

2014-01-05 Updated to link to earlier article.

Internal Project

I’ve decided to start a home project to test a few different technologies. The aim is to pick a a relatively simple project and implement this in a few different ways.

The simple project is a website where someone can post a status.

The rough outline is a website where:

  • Authenticated Users can:
    • post a status
  • Anonymous & Authenticated users can:
    • View current Status
    • View past statuses and search through them
    • ‘Like’ a Status

I guess you could call this twitter without most of the useful features.

I’m aiming to try a number of different technologies, in decreasing level of comfort.

I’ll also be swapping pieces in and out with new implementations in different technologies.

The current plan

  1. Document the UI – I’ve found this tends to make the implementation clearer
  2. Implement in bootstrap, MVC4 with SQL Server backend
  3. Swap the SQL Server backend for a No SQL database
  4. Design JSON API to access app
  5. Implement JSON api using WebApi backend
  6. Replace MVC app with javascript client side framework (currently planning to try angular)
  7. Replace the WebApi backend with an F# implementation
  8. Replace the WebApi backend with node.js
I want to apply best practices throughout, which might mean learning new best practices as I start using new technologies.

I’ll post all parts of the implementation and any documentation on Github.