A Mini SPA with ASP.NET MVC and AngularJS

4 minute read

SPA stands for Single Page Application; I think you already have little idea on it. Here I will demonstrate a mini SPA with ASP.NET MVC and AngularJS. So, let’s start.

Step 1: Create a ASP.NET MVC application with empty template

  • Open visual studio, Got to File->New->Project
  • Select Template -> Visual C# -> Web -> ASP.NET MVC 4 Web application and click OK
  • Select Empty Template and Razor as view engine

Step 2: Install required packages

  • Run the following command in Package Manager Console (Tools->Library Package Manager->Package Manager Console) to install required package.
  • Make sure your internet connection is enabled.
PM> Install-Package jQuery
PM> Install-Package angularjs -Version 1.0.7
PM> Install-Package Newtonsoft.Json

Step 3: Create View model
In this application I will try to demonstrate two pages for Trainer and Training. For this purpose, create TrainerVM, TrainingVM, RegistrationVm view model in Model folder. JSONBuilder is a class in Model folder which make model as json serialized.

public class TrainingVm
{
    public string TrainingCode { get; set; }
    public string Title { get; set; }
    public string Trainer { get; set; }
}



public class TrainerVm
{
    public string Name { get; set; }
    public string Email { get; set; }
    public string Venue { get; set; }
}



public class RegistrationVm
{
    public string Trainings { get; set; }
    public string Trainers { get; set; }
}

 
 
public class JSONBuilder
{
    public RegistrationVm BuildRegistrationVm()
    {
        var registrationVm = new RegistrationVm
        {
            Trainings = GetSerializedTraining(),
            Trainers = GetSerializedTrainers()
        };

        return registrationVm;
    }

    public string GetSerializedTraining()
    {
        var trainings = new[]
            {
                new TrainingVm {TrainingCode = "TRA001", Title = "ASP.NET MVC 4", Trainer="Mahedee Hasan"},
                new TrainingVm {TrainingCode = "TRA002", Title = "ASP.NET Web Form", Trainer="Asrafuzzaman"},
                new TrainingVm {TrainingCode = "TRA003", Title = "AngularJs Fundamental", Trainer="Foysal Alam"},
                new TrainingVm {TrainingCode = "TRA004", Title = "ASP.NET MVC 5 with web API", Trainer="Asfaquzzaman"},
            };
        var settings = new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() };
        var serializeCourses = JsonConvert.SerializeObject(trainings, Formatting.None, settings);
        return serializeCourses;
    }


    public string GetSerializedTrainers()
    {
        var trainers = new[]
            {
                new TrainerVm {Name = "Mahedee Hasan", Email = "mahedee.hasan@gmail.com", Venue="Leadsoft Bangladesh Ltd"},
                new TrainerVm {Name = "Asrafuzzaman", Email = "asraf@gmail.com", Venue="Leadsoft Bangladesh Ltd"},
                new TrainerVm {Name = "Foysal Alam", Email = "foysal@gmail.com", Venue="Leadsoft Bangladesh Ltd"},
                new TrainerVm {Name = "Asfaquzzaman", Email = "asfaq@gmail.com", Venue="Leadsoft Bangladesh Ltd"},
            };
        var settings = new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() };
        var serializedInstructors = JsonConvert.SerializeObject(trainers, Formatting.None, settings);
        return serializedInstructors;
    }
}

Step 4: Create a RegistrationController in controller folder

public class RegistrationController : Controller
{
    private JSONBuilder jsonBuilder = new JSONBuilder();

    public ActionResult Index()
    {
        return View(jsonBuilder.BuildRegistrationVm());
    }

}

Step 5: Create TrainingController and TrainerController

  • Create TrainingsController.js and TrainersController.js in Scripts->Application->Controllers folder

TrainersController.js

'use strict';
 
registrationModule.controller("TrainersController", function ($scope, registrationData) {
    $scope.trainers = registrationData.trainers;
});

TrainingsController.js

'use strict';
 
registrationModule.controller("TrainingsController", function ($scope, registrationData) {
    $scope.trainings = registrationData.trainings;
});

I will define registrationModule and registrationData in next steps.

Step 6: Create registrationModule

  • Create registrationModule.js in Scripts->Application. This is the configuration file for angular routing in client side.
var registrationModule = angular.module("registrationModule", [])
    .config(function ($routeProvider, $locationProvider) {
        $routeProvider.when('/Registration/Trainings', {
            templateUrl: '/templates/Trainings.html',
            controller: 'TrainingsController'
        });
 
        $routeProvider.when('/Registration/Trainers', {
            templateUrl: '/templates/trainers.html',
            controller: 'TrainersController'
        });
 
        $locationProvider.html5Mode(true);
    });

Here you might see that I map template and controller on corresponding routing. But I didn’t declare template yet. I will declare template in next steps.

Step 7: Create a layout page

  • Create a layout page in Views-> Shared ->_Layout.cshtml and add reference of angularjs, jquery and registration module.
<html ng-app="registrationModule">
    <head>
        <script src="~/Scripts/angular.min.js"></script>
        <script src="~/Scripts/jquery-2.1.1.js"></script>
        <script src="~/Scripts/Application/registrationModule.js"></script>
 
        <title>Training Registration</title>
        @RenderSection("JavascriptInHead", required:false)
    </head>
    <body>
        @RenderBody()
    </body>
</html>

Step 8: Create Index view

  • Right click on Index action of Registration controller and add a view. Modify the view as follows.
@model MiniSPA.Models.RegistrationVm
 
@{
    ViewBag.Title = "Training Regirstration";
    Layout = "~/Views/Shared/_Layout.cshtml";
}
 
@section JavascriptInHead
{
    <script src="~/Scripts/Application/Controllers/TrainersController.js"></script>
    <script src="~/Scripts/Application/Controllers/TrainingsController.js"></script>
    <script type="text/javascript">
        registrationModule.factory('registrationData', function() {
            return {
                trainings: @Html.Raw(Model.Trainings),
                trainers: @Html.Raw(Model.Trainers)
                };
        });
    </script>
}
 
<div>
    <div>
        <div>
            <div>
                <ul>
                    <li><span>Training Registration</span></li>
                </ul>
            </div>
            <div>
                <ul>
                    <li><a href="/Registration/Trainings">Trainings Details</a></li>
                    <li><a href="/Registration/Trainers">Trainer Details</a></li>
                </ul>
            </div>
        </div>
    </div>
    <div ng-view></div>
</div>

Step 9: Create template

  • Create training.html and trainer.html in templates folder as follows

Trainer.html

<div class="row">
     <div class="span10">
         <h2>Instructors</h2>
     </div>
 </div>
 <div class="row">
     <div class="span10">
         <table class="table table-condensed table-hover">
             <tr>
                 <th>Trainer Name</th>
                 <th>Email</th>
                 <th>Venue</th>
             </tr>
             <tr ng-repeat="trainer in trainers">
                 <td></td>
                 <td></td>
                 <td></td>
             </tr>
         </table>
     </div>
 </div>

Training.html

<div>
        <div>
            <h2>Training Details</h2>
        </div>
    </div>
    <div>
        <div>
            <table>
                <tr>
                    <th>Training Code</th>
                    <th>Training Title</th>
                    <th>Trainer Name</th>
                </tr>
                <tr ng-repeat="training in trainings">
                    <td></td>
                    <td></td>
                    <td></td>
                </tr>
            </table>
        </div>
    </div>

Step 10: Modify RouteConfig.cs

  • Modify the RouteConfig.cs as follows for routing Registration controller default and catching all other parameter.
public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapRoute(
        name: "Mini SPA",
        url: "Registration/{*catchall}",
        defaults: new { controller = "Registration", action = "Index", id = UrlParameter.Optional }
        );


        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Registration", action = "Index", id = UrlParameter.Optional }
        );
    }
}

This structure is not best. So it is not recommended for large application. For large application use service. Hope, I will publish a complete SPA soon. Thanks for your patient!

Source code