Developing hybrid Single Page Applications (SPA) using ASP.NET MVC,WebApi + AngularJs

Why mini-spa/hybrid-spa? Let’s see the pictorial difference between a traditional page lifecycle and a SPA (Single Page Applications) lifecycle –


Reference: http://msdn.microsoft.com/en-us/magazine/dn463786.aspx

One of the key benefit I see in following the SPA design principles for developing rich, complex web applications is the “stateful”ness we get [HTTP being stateless protocol by nature is one of the biggest disadvantage we know it is for building web apps vs say native apps.]. For complex web apps, it may be too idealistic to have just one “full” initial http request to get a page, and then subsequent async calls to load further pages or data. However, we can do it module-wise i.e. certain parts of the web app follow SPA design, others may or may not follow SPA design. This is referred to as mini-spa or hybrid spa.

Using AngularJs framework, I've come up with a sample application which follows SPA design principles. I’m using angular route module ngRoute along with angular directive ngView to define routes – controller & view associated with each route. It is essentially MVC pattern on the client-side. Moreover, our app is now route-driven on client-side. [The browser back and fro buttons are supported]

In the sample web app, we have two modules – music (music albums) and movies (movie dvds). In each module, user can filter results and view/edit the record. [NOTE: using mvc music store database from codeplex. Source]

For each module, I've defined corresponding angular module -


The route configuration for music module is as follows –

(function (app) {
    var routeConfig = function ($routeProvider) {
        $routeProvider.when("/", {
            controller: "musicAlbumListController",
            templateUrl: window.miniSpaApp.rootUrl + "MusicAlbums/List",
            reloadOnSearch: false
        }).when("/:genreId", {
            controller: "musicAlbumListController",
            templateUrl: window.miniSpaApp.rootUrl + "MusicAlbums/List",
            reloadOnSearch: false
        }).when("/Detail/:id", {
            controller: "musicAlbumDetailController",
            templateUrl: window.miniSpaApp.rootUrl + "MusicAlbums/Detail",
            reloadOnSearch: false
        }).when("/Edit/:id", {
            controller: "musicAlbumEditController",
            templateUrl: window.miniSpaApp.rootUrl + "MusicAlbums/Edit",
            reloadOnSearch: false
        }).otherwise({ redirectTo: "/" });
    };
    routeConfig.$inject = ['$routeProvider'];
    app.config(routeConfig);
})(angular.module("musicAlbumsApp"));

Each route maps to an angular controller and a view/template. 

In our main page (MusicAlbums - Index View), we include the angular scripts and define our container div using ngView directive to load different views, as follows –
@section HeadContent
{
    @Scripts.Render("~/bundles/angularMusicAlbums")
}
<div data-ng-app="musicAlbumsApp" data-ng-view="" data-ng-cloak="">
</div>

Similarly, for movie module we've defined it's route configuration and container div using ngView directive.

Complete sample application is located here.

Labels: , , , , , , ,