Sunday, July 20, 2014

Visual Studio Angular Project without using Templates

There are several Visual Studio templates which quick start your Angular development. I also created one template. If you are interested please go over to here. You can also download the source code of this blog at my github site.

These templates are great for a quick start, but one issue is that these templates create more or less functionality than we really need. Another issue is that we may not understand the purpose of all the files. If you are like me, then you want to know the plumbing code. In this blog I will go over step by step instructions on building an MVC Angular project without using Visual Studio Templates.

In my project I am planning to include the following javascript libraries. Please see below the list of libraries along with its purpose and location where you can download them. Where ever possible let’s download the non-minified version, we will use our .NET bundling to bundle these files. Alternatively you can use CDN also.
  • AngularJS
         https://angularjs.org  
  • AngularJS Route – For routing with our single page application
         https://angularjs.org  
  • Bootstrap – We will use this primarily for layout and responsive design. If need you can also use its JavaScript components such as DatePicker (you may need bootstrap directives for this)
  • Kendo UI Core with Angular Directives – These are open source UI controls from Telerik. These includes Angular directives. This is optional
  • JQuery – You may not need this but if you are using KendoUI then you need this

In addition to these javascript libraries we also need some nuget packages, they are:

  • Microsoft ASP.NET MVC – For the start up file
  • Microsoft ASP.NET Web API – For Ajax requests from Angular
  • Microsoft.AspNet.Web.Optimization – For bundling and minification of javascript and css

As our project main UI components are Angular, Kendo & Bootstrap, let us call our project as AngularKendoBootstrap. So let’s get started.

Fire up Visual Studio to create our project.

  • In Visual Studio 2013 create an ASP.NET Web Project and give the name as AngularKendoBootstrap     

  • While creating the project select an empty template


  • As you see we have a blank project in our solution explorer


  • Using Nuget Install ASP.NET MVC


  • Similarly install Web API


  • Using Nuget install the ASP.NET Web Optimization framework. This is used for bundling and minification


  • After installing using Nuget, create the following folder structure. As you are aware this is a typical MVC folder structure with an addition “app” folder


  • As per the MVC folder structure let’s include the files
  • Under the script folder include all the javascript files we downloaded


  • Similarly include the css files under the content folder


  • As recommended by MVC add the config files in the App_Start folder. These are the standard config file for any typical MVC & Web API project.


  • Add global.asax file and call our configs from it
protected void Application_Start(object sender, EventArgs e)
{
    WebApiConfig.Register(GlobalConfiguration.Configuration);
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    BundleConfig.RegisterBundles(BundleTable.Bundles);
}

  • Let’s bundle all out javascripts and css files using Bundle.config. In addition let’s also bundle all the our javascript files (that we place under app folder)

//including all the libraries used in our app such as angular
bundles.Add(
    new ScriptBundle("~/scripts/libraries")
        .Include("~/scripts/angular/angular.js")
        .Include("~/scripts/angular/angular-route.js")
        .Include("~/scripts/bootstrap.js")
        .Include("~/scripts/jquery.js")
        .Include("~/scripts/kendo/kendo.ui.core.js")
    );

//including all the css used in our app
bundles.Add(
    new StyleBundle("~/content/css")
        .Include("~/content/normalize.css")
        .Include("~/content/bootstrap/bootstrap.css")
        .Include("~/content/bootstrap/bootstrap-theme.css")
        .Include("~/content/kendo/kendo.common.css")
        .Include("~/content/kendo/kendo.blueopal.css")
        .Include("~/content/app.css")
    );

//including the javascript files in our app
bundles.Add(
     new ScriptBundle("~/scripts/app")
     .Include("~/app/app.js")
     .IncludeDirectory("~/app""*.js"true)
      );
  • Let’s create a HomeController and a correspond view. This serves the starting page for our angular app. Here is code for our MVC view

<html data-ng-app="AngularKendoBootstrapApp">
<head>
    <meta name="viewport" content="width=device-width" />
    <title> Angular Kendo Bootstrap Application</title>
    @Styles.Render("~/Content/css")
</head>
<body>

    <a href="/home">Home</a> <a href="/contact">Contact</a>
    <div data-ng-view>
        <div id="splash" class="splash">
            Loading ...
        </div>
    </div>
        @Scripts.Render("~/scripts/libraries")
        @Scripts.Render("~/scripts/app")
</body>
</html>

In the above as you see we defined an angular app “AngularKendoBootstrapApp” and included all the necessary javascript files

This completes our MVC setup. Let move to the Javascript part of our setup
  • Create the following directory structure for app folder. This is the directory structure we will use for our angular scripts.

  • In our app.js define the routing for our pages in the app as shown below:
angular.module('AngularKendoBootstrapApp', ['ngRoute'])
  .config(function ($routeProvider, $locationProvider) {

    $routeProvider
        .when("/home", {
                controller: "home",
                templateUrl: "/app/home/home.html"
            })
        .when("/contact", {
            controller: "contact",
            templateUrl: "/app/contact/contact.html"
        })
        .otherwise({ redirectTo: "/home" });
    $locationProvider.html5Mode(true);
});

We are done J. We built an Angular app from scratch without using any templates. Compile your project and run it.

You can find the source code of this project at my github site

You can also download the Visual Studio template file for this project from here.

10 comments:

  1. Nice article. The only hiccup I ran into is that a prerequisite for success is to either be using VS 2013, or be using VS 2012 with the ASP.NET and Web Tools 2013.1 for Visual Studio 2012 package installed.

    ReplyDelete
  2. Thanks for your feedback.

    I haven't tried with any other Visual Studio version as I have upgraded all my machines with Visual Studio 2013. I will try to get a VS 2010 and update this post accordingly

    ReplyDelete
  3. Nice job; thanks. When describing config files youo say, "These are the standard config file for any typical MVC & Web API project." So I should copy them from an existing project? Tell VS to create them as config files (I don't see an option for that)? Create empty C# files?

    Thanks.

    ReplyDelete
    Replies
    1. You can copy the files under App_Start folder from an existing project or get them from my github project at this url https://github.com/prasannapattam/AngularKendoBootstrap/tree/master/AngularKendoBootstrap/AngularKendoBootstrap/App_Start

      Delete
  4. You say, "Let’s create a HomeController and a correspond view. This serves the starting page for our angular app." I create the controller (fine), and then rt-click on the Views | Home folder and ask for an empty view. It does it, but it also creates or brings in several script files, _Layout.cshtml, _ViewStart.cshtml, and so on. Expected? If not, should I be creating the view differently?

    Thanks.

    ReplyDelete
    Replies
    1. You don't need the layout pages. As we will have only one view. Easiest is delete those files.

      For generating the view, in the controller right click the action method and then click Add View, don't check any checkboxes in the Add View dialog and click Add button. This should generate the view page without any other files

      Delete
  5. In your downloaded app (from git) I see your home.js and contact.js controllers. They both return an object (the object called vm). I haven't seen anywhere in the angular doc that tells me why the controller is returning anything. (Perhaps I haven't looked hard enough; bad on me!) Can you point me to the doc that describes this, and/or reply with a quick summary of that? (My guess: whatever a controller returns is placed in $scope under the controller's name.) (Again, very nice job on this!)

    ReplyDelete
    Replies
    1. I am using revealing module design pattern. Please take a look at my blog on this
      http://www.spaprogrammer.com/2014/08/revealing-module-pattern-in-angularjs.html
      Also I am using the ControllerAs syntax along with the revealing module pattern.

      As you know with AngularJS 2.0, $scope is going away and my approach is somewhat in line with the new angularjs design. I try my best to avoid $scope in my code.

      Delete
    2. Thanks again. I was familiar with the Revealing Module pattern. What confused (confuses) me is that I did not realize that what the controller returns will be available to the view, and I can't find reference to this in the documentation. (Again, that's probably my problem that I can't find it.) Can you point me to the Angular doc that talks about controller returning something and having that available to the view (html page)?

      Delete
    3. I don't think returning from controller is specific to Angular, hence you may not find it in Angular docs.

      I believe this is what happens when you call a controller using controllerAs syntax

      $scope.vm = new person() // declared as "person as vm"

      As per ECMA script specification the person can return the person object or any other object. In my scenario I am returning a different object (using revealing module pattern). This object will be available in the view as "vm". if I don't return the vm, then the controller object is available in the view.

      With Angular 1.3, returning from the controller is not allowed when using ng-controller. You can still use returning when using with routing.

      Delete