Skip to content
January 4, 2013 / jphoward

End to end web app in under an hour–Part 1

Here is the video tutorial that goes with this post:

Here’s how to create a complete web app in under an hour. We will (naturally!) create a todo app. The features:

  • Create, update, delete a todo
  • Sort (and show sort order)
  • Search
  • Pagination

We’ll try to make it somewhat user friendly, e.g.

  • Date-picker widget for todo due date
  • Enable/disable buttons as appropriate for context

Our infrastructure will be:

  • Backend Language: C#
  • Backend Framework: WebApi
  • Database: SQL Server (including SQL Express LocalDB during development)
  • ORM: Entity Framework Code First + Migrations
  • Frontend Framework: AngularJS
  • CSS styles: Bootstrap
  • IDE: Visual Studio + Resharper
  • Hosting: Appharbor

As you’ll see, this particular choice of tools is well suited to rapid application development, and is also very flexible.

The goal is not just to throw together the minimal necessary to have something working, but to create a really flexible infrastructure that we can use as a foundation for many future applications.  OK, let’s get started.

The Backend

In Visual Studio, create a new document and choose to create an MVC web application project.

image

Use the web API template.

image

Web API is a framework which makes it easier to create REST APIs. It is very similar to ASP.net MVC.

Delete HomeController.cs, everything in the Content folder, and everything except Web.config in the Views folder. (These are all for using ASP.Net MVC views and default styles, none of which we’ll need).

By default the API will use XML, but we would prefer JSON (this makes it a little easier to debug), therefore add this to the end of WebApiConfig.Register():

config.Formatters.XmlFormatter.SupportedMediaTypes.Remove(
                config.Formatters.XmlFormatter.SupportedMediaTypes.FirstOrDefault(t => t.MediaType == "application/xml"));

Now, create a new class for your Todo Items:

public class TodoItem {
        public int TodoItemId { get; set; }
        public String Todo { get; set; }
        public byte Priority { get; set; }
        public DateTime? DueDate { get; set; }
    }

And now we’re ready to create our REST API! After compiling, right-click the Solution Explorer, and choose Add->Controller, and create a controller called TodoController.

image

You’ll need to choose the option to create a new data context.

You should now have a working REST API! Press F5 to run your solution, and it should open in a browser. You will get a “not found” error since we don’t have any pages set up yet, so you’ll need to modify the URL path to ‘/api/todo’.

image

Of course, at this stage all we get is an empty array. We need to put some items into our database! First, check out SQL Server Object Browser to see that Visual Studio has already created a DB for us:

image

To add items, we are going to use Entity Framework Migrations. We will go to Tools->Library Package Manager in order to open the Package Manager Console, which is where we can enter commands to work with Entity Framework. In the console, type “Enable-Migrations”.

image

This has created a file for me called Configuration.cs, which allows me to specify data to seed my DB with. Let’s edit that now to seed some data.

protected override void Seed(AmazingTodoContext context) {
    var r = new Random();
    var items = Enumerable.Range(1, 50).Select(o => new TodoItem {
        DueDate = new DateTime(2012, r.Next(1, 12), r.Next(1, 28)),
        Priority = (byte)r.Next(10),
        Todo = o.ToString()
    }).ToArray();
    context.TodoItems.AddOrUpdate(item => new { item.Todo }, items);
}

Any time I change my model or edit Seed(), I’ll need to run Update-Database in Package Manager Console to have the DB show my changes to the code.

image

Now I’ll refresh my browser to see the data via the REST API:

image

The Basic AngularJS setup

Now that the API is working, we can create a simple page to show a list of todos. We will use AngularJS as our Javascript MVC framework, so let’s install that: simply type “Install-Package angularjs” at the package manager console. We’ll be using Bootstrap to style things up, so install that too: “Install-Package Twitter.Bootstrap”. In the root of your project, create index.html, with references to the css and js files we’ll be using.

<!DOCTYPE html>
<html ng-app="TodoApp" xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <script src="Scripts/jquery-1.7.1.js"></script>
        <script src="Scripts/angular.js"></script>
        <script src="Scripts/angular-resource.js"></script>
        <link rel="stylesheet" type="text/css" href="Content/bootstrap.css" />
        <title>Amazing Todo</title>
    </head>
    <body>
        <div class="container">
            <div ng-view></div>
        </div>
    </body>
</html>

You will need to change the ng-app attribute in the html element, and the title, for each of your projects. Other than that, your index.html will be the same for most of your projects (other that having some different js and css links, of course). All the actual work will occur in AngularJS templates. In order for AngularJS To know what template and controller to use we need to set up some routes. To do this, we use the config method of the AngularJS module class. Let’s create a new JavaScript file for our AngularJS code; the convention is to call this app.js.

var TodoApp = angular.module("TodoApp", ["ngResource"]).
    config(function($routeProvider) {
        $routeProvider.
            when('/', { controller: ListCtrl, templateUrl: 'list.html' }).
            otherwise({ redirectTo: '/' });
    });

This creates a route for ‘/’ that uses a controller called ListCtrl and a template called list.html.

Let’s create an empty controller in app.js.

var ListCtrl = function($scope, $location) {
    $scope.test = "testing";
};

Let’s create a basic list.html as well.

<h1>Test {{test}}</h1>

Any properties and methods of $scope are made available automatically in the template. In the template, use ‘handlebars’ (double braces) to indicate where AngularJS expressions should be placed. Don’t forget to add a script element to index.html pointing at your app.js. Now try going to http://localhost:5127/index.html in your browser (you’ll need to change the port of course). If it’s working, you’ll see “Test testing”.

The List Page

Let’s edit our list.html to do something more useful!

<table class="table table-striped table-condensed table-hover">
    <thead>
        <th>Todo</th>
        <th>Priority</th>
        <th>Due</th>
    </thead>
    <tbody>
        <tr ng-repeat="item in items">
            <td>{{item.Todo}}</td>
            <td>{{item.Priority}}</td>
            <td>{{item.DueDate}}</td>
        </tr>
    </tbody>
</table>

For this to do anything, we will need $scope.items to contain our todos. We can define in app.js an AngularJS $resource that we can use to query our REST API.

TodoApp.factory('Todo', function($resource) {
    return $resource('/api/todo/:id', { id: '@id' }, { update: { method: 'PUT' } });
});

var ListCtrl = function ($scope, $location, Todo) {
    $scope.items = Todo.query();
};

$resource is a function provided by AngularJS that creates an object for accessing a REST API. We use a factory method so that we can reuse the object without it getting recreated every time. Note that we also had to add a parameter to ListCtrl in order to have access to this object.

At this point, you should be able to view the list in your browser.

image

It’s interesting to note that all the html files are entirely static – the only thing that’s dynamic is the JSON sent by the web API.

That’s the end of Part 1 of this walkthrough. In the next part, we’ll add sorting, searching, and pagination to the list.

Continued in Part 2.

About these ads

36 Comments

Leave a Comment
  1. Mikael Brandt / Jan 31 2013 6:45 am

    Nice tutorial! Thanks.
    I have two questions though:
    1. After installing AngularJS in Visual Studio i still get errors from the code validator on “ng-app” and “ng-view”, am i missing something or is it because i run the express version?
    In the video you type “ngindex” and get code completion for that, pretty much like “prop”. How do you do that? I have no snippets for that…?

    Thanks in advance!

    //Mikael

  2. Gokul K / Mar 3 2013 3:31 am

    Excellent tutorial..Thanks for the video and the blog post..

  3. Pinal Bhatt (@pbdesk) / Mar 7 2013 11:47 pm

    Great Tutorial. Best tutorial I could find for AnjularJS with .Net. Nice explained the concepts. Great work Jeremy Howard.

  4. Natukula Murali Krishna / Mar 20 2013 7:05 pm

    Hi thanks for the excellent videos. Can you please tell me how you are getting bootstrap intellisense in visual studio if you have the bootstrap-vsdoc.js file can you please share that with us.

    Thanks & Regards,
    N.Murali Krishna.
    muralinit@gmail.com

  5. drandane / Apr 18 2013 12:52 am

    What is the tool you use to create your HTML page and generate your index page code?

  6. Xi Yu / Jun 25 2013 2:36 am

    How can I get angular intellisense like you did (ngi show all index structure)? I know how to make ng-app show intellisenselly, but how to show like this

    (pic in picpaste)
    http://picpaste.com/ngi-15MegLSO.jpg

    thanks

  7. Bastian Migge / Jul 25 2013 9:04 pm

    Hi there,
    great tutorial for starting with AngularJS and RESTful APIs. Thnk you so much. I implemented the flask-version and fixed some typos. Feel free to download or even join me to extend the software at https://bitbucket.org/bami/todo/overview

    Bastian

  8. didepix / Aug 21 2013 7:44 pm

    Hello,
    Great Tutorial. Thank you ;-)

    Juste one question, you type template resharper for ex ngdir,
    I have downloaded angular template form resharper website and i can not found this template (and other show in the video)

    Could you help me ? , Where can i found the other template please

    Thank you
    Best regard
    Didier

  9. Matt Herb / Aug 23 2013 4:34 am

    best tutorial of the year… Without this I dunno how I woudlve gotten started using angular/MVC web api… I cant really find anything else out there that gets me started with this combo.. and its good and basic.. but covers the basic CRUD scenerios which is helpful

  10. Quynh D Nguyen / Sep 26 2013 4:16 pm

    Thanks for an awesome tutorial!
    If anyone want to check out the source code for this tutorial, you can fork or clone my repo on github. I am on part 2 so far but planning to finish within next few days. Main different is that I used Parse REST API as my backend server instead of rolling one my own.

    https://github.com/QuynhNguyen/lets-learn-angularjs

  11. nikl0666 / Dec 12 2013 6:40 pm

    i Cant get the NG-View routing to work?

    • nikl0666 / Dec 12 2013 7:34 pm

      actually its the angularJS version that wont work…
      if i use it works with some modifications but then i get some other errors.. what am i doing wrong?

      • Chad Miller (@FakeChadMiller) / Dec 21 2013 4:58 am

        Newer versions of angular require you to add the ‘angular-route.js’ file in separately.

  12. Allan Rysin / Dec 25 2013 12:07 pm

    I ran into errors with routing and as Chad Miller mentioned, I need to add a reference to angular-route.js to my index.html file and I needed to change the dependency of ngResource to ngRoute in the app.js file

    • Allan Rysin / Dec 25 2013 12:24 pm

      Correction: Needed to added ngRoute in addition to ngResource

      • Clifford Eby / Dec 28 2013 3:28 am

        Can you show me how you add both ngRoute and ngResource in the app.js file?

      • David Revivo / Dec 30 2013 7:13 pm

        var TodoApp = angular.module(“TodoApp”, ["ngRoute", "ngResource"]).

  13. Saravana Sachi / Jan 28 2014 6:49 pm

    Thank you so much.

  14. Paul Pacurar (@paulpacurar) / Mar 12 2014 8:35 pm

    great tutorial and well explained; but the code snippets for angularjs cannot be found anywhere… Can you provide them?

  15. Elvin Arzumanoğlu / Mar 19 2014 4:20 pm

    This code doesn’t work((. I copy and past all your code from blog, but doesn’t work. How can I download code sample for this. I look for finding an wrong codes, but cant all my code as in an example. Please help me, I spend a lot times for watching this tutorial.
    

  16. Alesandro de Lima / Apr 4 2014 6:24 am

    For those that this does not work….. There have been a few changes recently to routing.

    angular.module(“sentryApp”, ["ngResource", "ngRoute"]). <== add ngRoute.

    In addition

    Make sure you use the following files above your script.

    Enjoy!

    • Alesandro de Lima / Apr 4 2014 6:25 am

      “js/angular.min.js”
      “js/angular-route.min.js”
      “js/angular-resource.min.js”

  17. dhiraj sonavane / May 5 2014 6:38 pm

    I spent 4 days in tension why my grid was not filling with data.

    I am using Visual Studio 2013
    I followed exact steps mentioned in tutorial but still my grid was not filling with data.
    As I am new to AngularJS, didn’t know where is the exact problem.

    Then after changing versions after versions finally issue is solved.

    My Index.html now is:
    ———————————————————————————————————–

    Amazing Todo

    ———————————————————————————————————–
    My app.js now is:
    ———————————————————————————————————–
    var TodoApp = angular.module(“TodoApp”, ["ngRoute", "ngResource"]).
    config(function ($routeProvider) {
    $routeProvider.
    when(‘/’, { controller: ListCtrl, templateUrl: ‘list.html’ }).
    otherwise({ redirectTo: ‘/’ });
    });

    TodoApp.factory(‘Todo’, function ($resource) {
    return $resource(‘/api/todo/:id’, { id: ‘@id’ }, { update: { method: ‘PUT’ } });
    });

    var ListCtrl = function ($scope, $location, Todo) {
    $scope.items = Todo.query();
    };
    ———————————————————————————————————–

    I am still into learning phase but as soon as I got the solution of problem, I thought to put here so that others will not waste their time.

    • dhiraj sonavane / May 5 2014 6:39 pm

      I spent 4 days in tension why my grid was not filling with data.

      I am using Visual Studio 2013
      I followed exact steps mentioned in tutorial but still my grid was not filling with data.
      As I am new to AngularJS, didn’t know where is the exact problem.

      Then after changing versions after versions finally issue is solved.

      My Index.html now is:
      ———————————————————————————————————–

      Amazing Todo

      ———————————————————————————————————–
      My app.js now is:
      ———————————————————————————————————–
      var TodoApp = angular.module(“TodoApp”, ["ngRoute", "ngResource"]).
      config(function ($routeProvider) {
      $routeProvider.
      when(‘/’, { controller: ListCtrl, templateUrl: ‘list.html’ }).
      otherwise({ redirectTo: ‘/’ });
      });

      TodoApp.factory(‘Todo’, function ($resource) {
      return $resource(‘/api/todo/:id’, { id: ‘@id’ }, { update: { method: ‘PUT’ } });
      });

      var ListCtrl = function ($scope, $location, Todo) {
      $scope.items = Todo.query();
      };
      ———————————————————————————————————–

      I am still into learning phase but as soon as I got the solution of problem, I thought to put here so that others will not waste their time.

      • dhiraj sonavane / May 5 2014 6:41 pm

        I wonder why Index.html is not getting posted in my above posts.

        Anyway my head tag in Index.html is:

        Amazing Todo

  18. Jed I / May 9 2014 8:34 am

    I also had the empty list issue in VS2013.
    Implement ‘dhiraj sonavanes’ solution and do the following…

    In list.html change “item in items” to “todo in todos” and modify the elements accordingly:
    todo.Text
    todo.Priority
    todo.DueDate

  19. Brian Carlson / May 17 2014 12:50 am

    I am new to AngularJs. When I get to the step where you right-click in Soulution Explorer and go to Add->Controller, I am stymied. I don’t get that option. I can go to Add->new Item and then choose a controller but none of those give a dialog like you are showing. I don’t think any options I see are the right type of controller.

    • Brian Carlson / May 17 2014 12:51 am

      OK, just figured it out. I have to right-click on the “controllers” folder. then I get that option.
      Thanks for the tutorial.

  20. Jp de Beer / Jun 4 2014 12:28 am

    We had a big issue with inconsistency in the app.js file due to updated workings of AngularJS.

    We managed to get app.js working with AngularJS(Version 1.2.16).

    Here is the code:

    angular
    .module(“TodoApp”, ["ngResource", "ngRoute"])
    .config(['$routeProvider', function ($routeProvider) {
    $routeProvider.
    when('/', {
    templateUrl: 'list.html',
    controller: 'ListCtrl'
    }).
    otherwise({
    redirectTo: '/'
    });

    }])
    .factory(‘TodoFactory’, function($resource) {
    return $resource(‘/api/Todo/:id’, {id: ‘@id’ }, {update: { method: ‘PUT’ } });
    })
    .controller(‘ListCtrl’, ['$scope', 'TodoFactory', function ($scope, TodoFactory) {
    $scope.todos = TodoFactory.query();
    }]);

Trackbacks

  1. End to end web app in under an hour–Part 2 « Jeremy Howard
  2. Intermission–REST API in Python with Flask-Restless « Jeremy Howard
  3. Webapps for Data Scientists – Building your first CRUD | no free hunch
  4. PROG ASP.NET MVC4 - De moeite of toch maar bij Webforms blijven?
  5. Todo Web App Part 1 - ASP.NET MVC Angular Web API | Share You All

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 55 other followers

%d bloggers like this: