I did a brown-bag session at work this week on building a SPA (Single Page App) with Durandal, Knockout and Breeze. So I thought I might as well knock up a quick blog post as an overview of the talk too.
First I'll run through an overview of the components of the application, then I'll explain what I've sought to achieve in the different areas of the code. Finally, I'll post the code for anyone to look over if they wish.
What is a SPA
SPA stands for Single Page App, and to help explain what a SPA actually is it's important to understand the architecture behind a SPA.
A SPA is a move away from the traditional server-side application architecture we may be used to with ASP.NET MVC:
In this scenario the presentation, business and data logic is handled on the server-size.
Whereas, in a SPA the architecture is more based in the client-size:
So in the SPA architecture the presentation, UI logic and data/service access is client-side, with any business logic/service layers and/or database access handled in the server side.
But why is it called a "Single Page App"? That's because a SPA is typically a web application or website that once the inital page is loaded subsequent navigation and data loading are handled without a full page load.
Benefits of SPA
One of the main benefits of building a SPA is that is provides such a rich user experience. Because of the dependence on client-side technologies we can keep the user engaged because the pages move fluently and the experience is responsive.
Building a SPA
When building a SPA we generally have to address four main concerns/areas:
Routing - Navigating in the application, responding to URL updates. Also includes deep linking. A deep link reflects where the user is in the application. This allows users to bookmark and return to links within the application.
Applicaton Lifecycle - Provides access to events in the application lifecycle. For example, view loaded, view attached, etc.
Data Access - Access to WebAPI or Web Services.
Data Binding - Binding of data and entities to UI elements.
There are a number of SPA frameworks to use to achieve the four areas/concerns noted above. However, the ones I'm more familiar with can be seen below listed according to the areas/concernts they address:
If you can't guess from the title, this example of building a SPA will focus on using Durandal, Knockout and Breeze. I hope to do another post on building a SPA with Angular in the near future.
Durandal is essentially a SPA framework. It provides features such as:
- MV* Architecture
- JS & HTML Modularity
- Application Lifecycle
- Eventing, Modals, Message Boxes, etc.
- Navigation and Screen State Management
- Async Programming with Promises
Durandal has the following dependencies:
Knockout handles data binding. The key concepts of knockout are:
- Declarative Binding
- Automatic UI Refresh
- Dependency Tracking
Knockout has the following features:
- Small and Lightweight (46kb minified)
- No dependencies
- Supports all mainstream browsers
Breeze is a rich data framework and features the following:
- Client Caching
- Tracking Changes
- Rich Queries
Breeze has the following dependencies:
- Q (handling promises in async JS)
Demo Code Architecture
The architecture used in the demo application is as follows:
As can be seen above the demo application utilises WebAPI on the server size, which is accessed by Breeze to handle data access. Breeze then uses Knockout for databinding to UI elements. Whereas the routing and UI/View management is handled by Durandal.
The structure of the UI/views in the page is as follows:
Here we can see the demo application has an index page (index.cshtml) which contains the shell view, which is the default view. The default view then contains a view on the left (view one) and larger view on the right (view two) which is used for the main content area.
The demo code can be downloaded from:
I've also published the site to Azure, so you can view the finished product:
As an overview I'll quickly run through the different areas/projects in the solution and highlight any specific patterns or approaches I've taken.
Here we find all of the server side data access code. This code is using an Entity Framework Code First approach, and uses the Repository and Unit Of Work patterns.
You'll also notice that I abstract the entity configuration away from the actual entity classes. I prefer this approach as then the entity classes aren't coupled to any data access methods.
I've also created a Breeze specific Unit Of Work class. This class encapsulates the Breeze ContextProvider, which is used to manage saving changes to entities passed from the client-side.
Contains the entity/model classes.
Some unit tests I used while building the server side data access components.
The web project also includes a Web API (see Api folder). Here I've separated the data specific calls and the Breeze metadata call into separate controllers.
I hope that all made sense, and that it is useful to someone out there! Any questions or suggestions feel free to comment and I'll do my best to respond.