Single Page Application with MVC and AngularJS part 1

Single page applications give users a fluid and fast experience with no visible post-backs interrupting the flow. From a UX point of view this is great but UX is not the only aspect of a website that developers need to consider.

SEO, progressive enhancement and graceful degradation are some notable hurdles that SPA’s have to overcome. Ultimately we want the site to work with or without JavaScript, not break if a user navigates directly to specific URL and be fully index-able for SEO purposes.

In this tutorial series we will aim to build a very simple application that allows typical CRUD operations on a list of customers. Keeping graceful degradation in mind we first build the basic application without AngularJS, to me this makes sense in terms of the development order with additional layers built on top of a solid base. What we don’t want is an application which is 100% reliant on JavaScript for it’s functionality.

Although we are starting with a plain MVC application it should still be built with the end goal of a single page application in mind. We have to consider that our AngularJS app will need to use API calls to function, and as such we should make sure all our core functionality is cleanly separated.

Create the basic MVC application

Use a simple MVC start-up project to get the essential bits first. Next create a library project to separate out any business logic our site may have. For this example we are just using a single library to keep all our data access code in.

The library uses Entity Framework with code first models and a repository pattern to keep things clean. Create a model to represent our and decorate it with the relevant data attributes to enable validation.

public class Customer 
{
    public int Id { get; set; }

    public string FirstName { get; set; }

    public string Surname { get; set; }

    public string Telephone { get; set; }
}

To get Entity Framework to generate the actual DB tables create a DbContext.

public class CustomerDbContext : DbContext 
{
    public CustomerDbContext() : base("CustomerContext")
    {
    }

    public DbSet Customers { get; set; }
}

Using a simple generic repository pattern create the CRUD operations for the new model. I won’t go into to detail about this pattern you can find plenty of details on the ASP.NET tutorials.

 
public class CustomerRepository : ICustomerRepository
{
    private readonly CustomerDbContext _dbContext;

    public CustomerRepository()
    {
        this._dbContext = new CustomerDbContext();
    }
        
    public CustomerRepository(CustomerDbContext dbContext)
    {
        this._dbContext = dbContext;
    }

    public Customer Get(int id)
    {
        return this._dbContext.Customers.FirstOrDefault(x => x.Id == id);
    }

    public void Update(Customer entity)
    {
        this._dbContext.Entry(entity).State = EntityState.Modified;
    }

    public void Create(Customer entity)
    {
        this._dbContext.Customers.Add(entity);
    }

    public void Save()
    {
        this._dbContext.SaveChanges();
    }

    public IEnumerable FindAll()
    {
        return this._dbContext.Customers;
    }
}

Create a controller with actions for each of our CRUD operations, at this stage these will be separate routes or pages in our application. The use of the library classes means we should have relatively little code in our controller actions.

public class CustomerController : Controller
{
    private ICustomerRepository customerRepository;
    
    public CustomerController()
    {
        this.customerRepository = new CustomerRepository(new CustomerDbContext());
    }

    public CustomerController(ICustomerRepository customerRepository)
    {
        this.customerRepository = customerRepository;
    }

    public ActionResult Index()
    {
        var model = this.customerRepository.FindAll();
        return View(model);
     }

     public ActionResult Create()
     {
         return View();
     }

     [HttpPost]
     public ActionResult Create(Customer customer)
     {
         try
         {
             if (ModelState.IsValid)
             {
                    customerRepository.Create(customer);
                    customerRepository.Save();
                    return RedirectToAction("Index");
             }
         }
         catch
         {
             ModelState.AddModelError(string.Empty, "Could not save customer");
         }
         return View(customer);
    }

    public ActionResult Edit(int id)
    {
         var model = this.customerRepository.Get(id);
         return View(model);
    }

    [HttpPost]
    public ActionResult Edit(Customer customer)
    {
        try
        {
            if (ModelState.IsValid)
            {
               customerRepository.Update(customer);
               customerRepository.Save();
               return RedirectToAction("Index");
            }
        }
        catch
        {
            ModelState.AddModelError(string.Empty, "Could not save customer");
        }
        return View(customer);
    }
}

The views are created for each action, here we want to separate our views using partial views so the actual views become pretty straight forward, the reason for this will become clear in part 2.

First show all customers

@model IEnumerable<Customer>
@{
    ViewBag.Title = "Customers";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

@Html.Partial("~/Views/Partials/_ShowCustomers.cshtml", Model)

Create Customer

@model Customer
@{
    ViewBag.Title = "Create";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

@Html.Partial("~/Views/Partials/_CreateCustomer.cshtml", Model)

Edit Customer

@model Customer

@{
    ViewBag.Title = "Edit";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

@Html.Partial("~/Views/Partials/_EditCustomer.cshtml", Model)

And the partial views for create and edit, note the create and edit views are more or less the same so I have only shown the create form here.

@model Customer
<h2>Create</h2> <form name="create_form" method="post"> <div class="form-horizontal"> <h4>Customer</h4> <div class="form-group"> @Html.LabelFor(model => model.FirstName, "First Name") @Html.EditorFor(model => model.FirstName)
</div>
<div class="form-group">
@Html.LabelFor(model => model.Surname, "Last Name")
@Html.EditorFor(model => model.Surname)
</div>
<div class="form-group">
@Html.LabelFor(model => model.Telephone, "Phone Number")
@Html.EditorFor(model => model.Telephone)
</div>
<div class="form-group">
<input type="submit" value="Create" />
</div>
</div>
</form>
<div>
@Html.ActionLink("Back to List", "Index")
</div>   

Finally the main view to display a list of Customers. 

@model IEnumerable<Customer>
<h2>Customers</h2>
<p>
@Html.ActionLink("Create New", "Create")
</p>
<table>
<tr>
<th>First Name</th>
<th>Surname</th>
<th>Telephone</th>
<th></th>
</tr>
@foreach (var item in Model)
{
<tr>
<td>@item.FirstName</td>
<td>@item.Surname</td>
<td>@item.Telephone</td>
<td>@Html.ActionLink("Edit", "Edit", new { id = item.Id })</td>
</tr>
}
</table>

Once that is all done you should have a reasonable functioning application that allows users to be created, retrieved and updated. The full code project solution can be found on github.