If the plan doesn’t work, change the plan but never the goal.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi gravida sollicitudin egestas. Ut lobortis eros vitae mauris cursus, vel faucibus turpis volutpat. Duis aliquam eu nibh non molestie. Sed pretium sit amet tellus eu pellentesque. In sed dictum quam. Nullam pulvinar porttitor lorem, eget placerat sapien sodales eget. Quisque ac mattis dui. Nunc sodales nisl pretium, tempor felis et, sagittis purus. Nullam quis purus quam. Nulla ligula libero, luctus eget efficitur eu, ullamcorper non ex. Sed eget ullamcorper diam, non hendrerit lorem. Pellentesque imperdiet nec mi at malesuada. Sed gravida at tortor non interdum.

If the plan doesn’t work, change the plan but never the goal.

Nulla in consectetur ante. Vivamus elementum ultrices enim vel blandit. Donec facilisis diam quis molestie ultricies. Phasellus volutpat eros vel arcu aliquet luctus. Aliquam erat volutpat. Sed sed arcu at mi fringilla pellentesque at quis metus. Maecenas lacinia efficitur libero, sed congue risus eleifend quis. Cras lectus elit, fringilla eget erat vel, euismod gravida lacus. Nunc neque ex, ultricies non aliquet in, pretium rhoncus tellus. Curabitur at odio consequat, varius est nec, gravida elit. Donec et blandit ligula. Mauris eleifend, lacus ac gravida ullamcorper, nulla libero fermentum turpis, id pulvinar leo elit id orci. Vestibulum massa lacus, cursus eu faucibus lacinia, euismod vel metus. Ut et eleifend ex, ac laoreet odio.

In hac habitasse platea dictumst. Sed finibus mollis eros a viverra. Donec sollicitudin nisi et odio pulvinar rutrum. Phasellus laoreet feugiat porttitor. Sed lectus quam, molestie sed efficitur vel, suscipit non risus. Suspendisse vitae ex urna. Suspendisse facilisis, eros sed placerat aliquam, lectus libero viverra ligula, sit amet porttitor ante est eget nulla. Etiam interdum ante eget odio rutrum, vel posuere enim dapibus. Maecenas tortor erat, sodales quis orci non, malesuada tempor urna.

In iaculis, leo in semper imperdiet, magna sem dictum odio, nec interdum neque lorem vitae libero. Integer enim ex, interdum porta mollis ac, pellentesque eget augue. Phasellus maximus erat a dui fermentum dictum. Nam at congue nibh, sit amet malesuada mi. Curabitur est augue, gravida sed purus eget, tincidunt rhoncus lectus. Aliquam ornare molestie tortor sed pretium. Donec eu augue mauris. Phasellus eget tincidunt ipsum. Sed non mollis quam. Integer quis hendrerit diam. Mauris convallis arcu eget magna commodo ornare a sit amet libero. Aliquam tristique at arcu a venenatis. Mauris commodo tincidunt ipsum sit amet aliquet.

“I like big data for $400” – Implementing a Jeopardy! Question Explorer using DocumentDB, Azure Search, AngularJS and Electron – Part 1

The concept of NoSQL or schema-less databases refers to systems that store data in a schemaless fashion using some form of document notation such as JSON. Examples of NoSQL databases include: MongoDB, CouchDB, RavenDB and, as we will discuss in this post, Azure DocumentDB.
In this series, we will be creating an application that allows users to quickly browse and search a repository of over 200,000 jeopardy questions. We will use Azure DocumentDB as a data repository, Azure Search to implement full text search functionality and will use AngularJS and Electron to create a desktop client that users can use to browse these questions.

Continue reading

The ultralight angular application setup package – Part 2: Build process for large applications

In our last post, we discussed how to create four files that, when chained together with the appropriate commands, would build out the framework for your web app. Now we will show you how to tweak this process to create large application friendly project organization, as well as adding build processes into the mix. But first, lets go over some changes we made since the first blog entry.

Continue reading

DocumentDB and Azure Search at a SQL Saturday in Birmingham, AL

This Saturday, March 18, 2017, SQL experts from throughout the United States will be arriving in Birmingham, AL to speak at SQL Saturday #593. SQL Saturday is a free program supported by the Professional Association for SQL Server (PASS) and the Birmingham event is hosted by Steel City SQL, a SQL Users group located in Birmingham, AL. SQL Saturdays offer free training and community opportunities to professional developers, DBAs and SQL Server professionals. According to the SQL Saturday #593 website, this will be the sixth SQL Saturday offered in Birmingham, AL.

Continue reading

Angular Object Validator: Enforcing object types in an Angular.js application

As anyone with JavaScript experience will tell you, occasionally the Wild West of coding languages falls a little short in critical areas by not enforcing object types. On a small Angular application, where all the developers have intimate knowledge of the code base, this may not be an issue. However, as the project scales, and new people begin working in the solution, you may find yourself wishing you had a way to enforce object types within your more critical functions. At this point, you may be asking yourself “What about TypeScript?”. If you have the option to start fresh, and know that your application will require type enforcement, TypeScript is definitely the logical answer. However, there are times in which TypeScript might not be an option. (legacy code, etc.)

To help with this issue, here at Sigao we have created a solution specifically for Angular.js applications called Angular-Object-Validator. This simple service will provide a single entry point for loading and validating pre-defined objects against potentially dynamic objects within your application.

Installing Angular Object Validator

Via Bower:

bower install angular-object-validator --save

 

Once the package and its dependencies have been added to your project, your angular application should have access to a module called “ObjectValidator” which you will need to inject into your application.  Each controller that will use the validator needs to be injected with a variable called “objectValidator

 

Usage

Setting up the validator

Angular services behave as singletons, meaning once data has been changed inside the service, that data is accessible everywhere in the application that the service is used. Because of this, it is recommended to load all of your object models in one location via the command objectvalidator.addClass(“Class Name”, _yourModelObject).

 

Testing

Once the validator has ingested all of the classes, you can now validate objects at any point that you have injected the validator. To test a specific class, all you need to do is use objectValidator.test(“Class Name”, yourObjectVariable). This will return true for valid, and false for invalid

 

Configuration

Optionally, you may change the behavior of the validator by sending a configuration object to  objectValidator.config({}).  Object can contain a property called checkProto and matchPropertyCount, both of which are boolean values

 

Examples

1. Configuration property: checkProto

Default value: true. This configuration determines if prototyped properties are validated against the model.  Below is an example of 2 objects and how they compare with checkProto:

//Object 1
objectValidator.addclass("CheckProtoExample", {
     something:"",
     somethingElse:[]
});

//Object 2
function example() {
     this.something = "";
}
example.prototype = {somethingElse: []};
var testObject = new example();

objectvalidator.config({checkProto:true});
objectvalidator.test("CheckProtoExample", testObject); //Returns: true
objectvalidator.config({checkProto:false});
objectvalidator.test("CheckProtoExample", testObject); //Returns: false

2. Configuration property: matchPropertyCount

Default value: true.  This configuration decides if the validator matches the exact properties in the model, or if the tested object can have additional properties beyond those in the model.  Note that the tested object is always required to have at least all of the model objects properties.

objectValidator.addClass("matchPropertyCountExample", {
            test1: "",
            test2:[],
            test3:true,
            test4:{}
});

var testObject = {
            test1: "",
            test2:[],
            test3:true,
            test4:{},
            test5:"something",
            test6:{}
        }

objectValidator.config({matchPropertyCount: true});
objectValidator.test("matchPropertyCountExample", testObject);//Result: false
objectValidator.config({matchPropertyCount: false});
objectValidator.test("matchPropertyCountExample", testObject);//Result: true

 

3. Generic controller mock up

The following example is a mock up of a generic controller for interacting with a database. Keep in mind, because this is an example, it has not be tested and will likely need some extra work to be used. However, it illustrates how to effectively use the object validator in your application.

Module setup

(function () {
    "use strict";

    angular.module('YourModule', []).directive('YourDirective', yourDirective);
    yourDirective.$inject = ['$http', 'objectValidator'];

    function yourDirective($http, objectValidator) {
    
        //Your code goes here

    };
})();

Here we have the beginnings of our module, highlighting how to inject the object validator into the controller. All of the following code examples are placed inside the main controller function of this module, in the order that they are discussed.

 

Setting up the validator

//setting validator to match exact number of properties on objects as well as prototyped values
objectValidator.config({checkProto: true, matchPropertyCount: true});

//Load models into validator.  Because services are singletons, this can be done
//in one main controller for all of the critical objects in your site.  For the sake
//of time, we've defined them here
//Validator will use the type of the model property value for the validation
objectValidator.addClass("getDto",{
    status: 0,
    result: {
        property1: 0,
        property2: [],
        property3: ""
    }
});
objectValidator.addClass("postDto",{
    data: []
});

Now we are defining the models and configuring the validator. In larger applications it is recommended that loading the object models happens in one location for the whole application, rather than inside the controller. However, for this example we decided to simplify the process.  Keep in mind that the models must be defined using the type of variable you require.

Defining the functions

//Service model
var service = {
 getData: getData,
 setData: setDat
};
return service;

function getData() {
            return $http.get("http://yourURL.com/api/getData")
                .then(handleReturn)
                .catch(function (message) {
                    console.error(message);
                });
            function handleReturn(data, status, headers, config) {
                //make sure that inbound data matches structure of _dtoModel
                if (objectValidator.validateObject("getDto", data)) {
                    return data;
                } else {
                    console.error("YourDirective.getData received an invalid object format");
                    return null;
                }
            }
}
function setData(data) {
            if (objectValidator.validateObject("postDto",data)) {
                return $http.get("http://yourURL.com/api/setData")
                    .then(handleReturn)
                    .catch(function (message) {
                        console.error(message);
                    });
            } else {
                console.error("YourDirective.setData received an invalid object format");
                return null;
            
            function handleReturn(data, status, headers, config) {
                //optionally, you can validate the post return if you'd like
                return data;
            }
        }
}

Lastly, we define the functions for getting and setting the hypothetical data. We use the validator to compare the objects being sent and received against the models that we expect to send and receive. If they do no match, we handle the exception and alert the user.

 

Documentation

Name Description Argument Type(s) Returns
test() Tests an object against a pre loaded class String: Class Name,
Object: model
Bool: validation result
type() Returns the type of variable sent to it Var: input variable String: type of variable
addClass() Adds a class model into the validator to test data against String: Class Name,
Object: model
getClass() Gets a class that has been loaded into the validator String: model name Object: model object
removeClass()Gets a class that has been loaded into the validator Removes a class that has been loaded into the validator String: model name
getAllClasses() Gets all of the classes that have been loaded into the validator Object: object that contains all classes
removeAllClasses() Removes all classes in the validator
config() Sets configuration settings within the validator Object: Configuration object that contains 1-2 properties.  checkProto, and/or matchPropertyCount

 

How to Use AgileKit:Poker

Over the past month, the Sigao Studios team has been working on building AgileKit.IO, a suite of micro-tools designed to improve your agile team. Our first release is an agile estimation tool for playing agile estimation poker.

Create a game and invite friends

To begin playing poker, navigate to www.agilekit.io and press the green Create Game button.

AgileKit.IO Create Game Button
Once AgileKit has provisioned a new game room, you will be asked to give your name and an email address (If you have created a game in the past, you might not be asked again).
Poker Name and Email Dialog

The only thing we will use the email address for is to email you the results of the game at the end of the session.

Once you are in the game, you can send the room ID to your team so they can join you. They can do so by navigating directly to the link, or entering the 5-character code into the Join Game box on www.agilekit.io.

Poker Invitation Code

As your team members join, you will see them show up in the players list located in the top right of the game area.

Poker Players List

Create Some Product Backlog Items (PBIs)

In order to begin the game, you will need to add some PBIs to your game. If you have just created the game, you will have a blue dialog asking you to create a PBI. To do so, click the button. If you are in the game, you can add a new PBI by pressing the new PBI button located above the PBI list.

splashscreen

Poker New PBI Button

New PBIs show up in the PBI list located on the bottom right of the game screen.

pbilistwithitems

You can edit or delete a PBI using the icons next to each PBI.

Play the Game

Once you have PBIs entered and your team has joined you can begin playing the game. The first step is to select a PBI you want to estimate by clicking the PBI in the items list. When you do that, that PBI will show up on your team members game board and you can begin the discussion.

AgileKit Poker PBI Card

When you are ready to vote, your team members can select the vote card that they wish to vote.

votingcards

You will see their votes show up in your game board view.

Poker Votes Cast

When you are ready to see the votes, press the blue “Flip” button and everyone will see the votes.

Poker Votes Shown

Now, talk about the votes. Have the person with the lowest and highest explain why they voted the way they did. Promote open and frank conversation, and, if you reach consensus, enter the Score in the Score box on the PBI. If you would like to vote again, press the red Reset button and everyone will be able to cast another vote.

Poker Consensus Reached

When you are ready to view the next PBI, simply click on it in the Items window and it will show up for everyone and you can begin the voting process for that item.

Export the Game

Once you are ready to end the game, you can click the green Export button. You can do this as many times as you would like. You will be asked to complete a single question survey. Once you do that, press export and you will receive an email.

Poker Export Screen

Poker Email Results

Next steps

Sigao Studios is excited to offer this inaugural AgileKit tool. We have many more tools planned and are looking forward to creating a tool set that will help transform your agile and scrum organization. If you have any feedback or questions regarding this tool, please feel free to let us know. We are eager to hear how we can help your organization move forward in your agile methodology.

The ultralight angular application setup package – Part 1: Four files to rule them all

In this tutorial I will be walking you through a means of rapid angular application setup. By the end you should be able to run a single command and have a bare bones angular application built and ready for experimenting. By eliminating the overhead in setting up a project, I hope to encourage rapid development of bad ideas.

We will be using Node.js, gulp.js, and bower.js to setup the initial structure for a project. The final product of this tutorial will a foundation for a project but will not contain the build processes needed compile project script. Because of this, you will not be able to official “start” the project until the end of Part 2.s

Step one: The package.json file

As a quick disclaimer, this tutorial will be using Node.js extensively. If you do not have any experience with Node, I would recommend downloading and installing it from NodeJS.org and familiarizing yourself with its functions before attempting this.

Navigate to the project folder you would like to use for your Angular application and create a file called package.json. Enter the following code into this file and save.

{
  "name": "PackageName",
  "private": true,
  "version": "0.0.0",
  "description": "",
  "repository": "",
  "license": "",
  "devDependencies": {
    "fs-path": "^0.0.22",
    "gulp": "^3.9.1",
    "gulp-load-plugins": "^1.2.4",
     "http-server": "^0.9.0",
    "mkdirp": "^0.5.1"
  },
  "scripts": {
    "preinstall": "npm install -g bower && npm install -g gulp",
    "postinstall": "bower install && gulp setup",
    "start": "http-server -a localhost -p 8000 -c-1",
    "pretest": "npm install"
  },
  "dependencies": {}
}

While the package.json file offers a large number of useful tools, the area we will be focusing on in this case is the devDependencies and scripts properties. Note: the name field is required by Node and will throw errors if empty.

  • devDependencies: This is what node will use to define what node development packages to install when you run the initial “npm install” command on the project folder. Keep in mind, packages placed here should only be regarding the development process, not libraries used by the application (Those would go in the dependencies object, but in this instance we’ll be managing those with Bower)
  • scripts: These are command line scripts that will be executed during various node processes. As you can see, before the installation we are running a command to install Bower and Gulp globally. After those development tools are installed, we’re running two tasks (both of which we will define later), one to install the website dependencies defined in the bower.json file and one to run the gulp process to build the site structure.

Step 2: The bower.json file

Next, we will create a file called bower.json in the folder and define it as follows.

{
  "name": "Setup package",
  "description": "",
  "main": "",
  "authors": ["" ],
  "license": "",
  "keywords": [""],
  "homepage": "",
  "private": true,
  "ignore": [""], 
  "dependencies": {
    "angular": "^1.5.7",
    "bootstrap": "^3.3.6",
    "angular-route": "^1.5.7"
  }
}

Once again, we will be skipping over some parts of the object that are not relevant to what we’re doing. It is worth reading about how bower manages packages, but for the time being we will focus on the dependencies object.

  • dependencies: These are actual packages used by your website that are managed by bower. These can be automatically updated with bower commands entered manually or from a gulp process. For now, we’ll be using this file to simply install the packages in our project folder.

Step 3: The custom file

Next comes our definition of how the Angular application project should be organized. In the same folder, create a file called projectSetup.json with the following code. This object will be consumed by our custom processes defined in step 4. With this, we will define the folder layout of the project, the .gitignore file, and any template files we would like to create.

{
    "fileTree": {
        "working": {
            "app": {
                "components": {
                    "main": {
                        "files":[
                        "main.html",
                        "main.js" ]
                    } 
                },
                "files":["app.module.js","app.route.js","app.controller.js"],
                "shared": null
            },
            "assets": {
                "css": null,
                "img": null,
                "js": null,
                "less": null
            },
            "files": ["index.html"]
        },
        "public": {
            "css": null,
            "img": null,
            "js": null,
            "html": {
                "files": ["main.html"]
            },
            "files": ["index.html"]
        }
    },
    "gitignore": [ "node_modules", "bower_components" ],
    "templates": {
        "index.html": [
            "<!DOCTYPE html>",
            "<html lang=\"en\" ng-app=\"app\">",
            "<head>",
            "<meta charset=\"utf-8\">",
            "<title></title>   ",
            "<link rel=\"stylesheet\" href=\"css/index.css\" />",
            "<!--Scripts-->",
            "<script src=\"js/vendor-min.js\"></script>",
            "<script src=\"js/app.js\"></script>",
            "</head>",
            "<body ng-controller=\"mainController\">",
            "<div ng-view></div> ",
            "</body> ",
            "</html>"
        ],
        "app.module.js": [ "var app = angular.module(\"app\", [\"ngRoute\"]);" ],
        "app.controller.js": [
            "app.controller(\"mainController\", function ($scope) {",
            "$scope.msg = \"Hello World\";",
            "});"
        ],
        "app.route.js": [
            "app.config(function($routeProvider) {",
            "$routeProvider.when(\"/\", {",
            "templateUrl : \"html/main.html\"",
            "});",
            "});"
        ],
        "main.html": ["<div>{{msg}}</div>"]
    }
}
  • fileTree: This is how we will lay out the folder structure for the project, as well as defining any placeholder files we may want. Folder names will be decided based on any property that contains an object or a null value, while file names will be defined by any property with an array of file names. While we chose to use “files” for all of our file arrays, this isn’t strictly necessary.
  • gitignore: This is a simple array of items you would like to be added to a .gitignore file that will be generated.
  • templates: The properties of this object should exactly match the names of placeholder files that you’ve defined in your file tree. The array of strings will be formatted and injected into the file that matches the property name, allowing you to define some basic default functionality in the javascript/html files. Note: this was written with the intention of keeping everything within a single file. While I will not be covering it in this tutorial, it would be fairly easy to convert the functions in step 4 to accept file paths that point to template files, rather than arrays of strings. You do you.

Step 4: The gulpfile.js file

This file will be the backbone of our setup process for our Angular application. For now, we will only use it for generating the folder/files structure, generating the .gitignore file, and injecting default code into our auto generated files. However, in the next tutorial we will also be defining build processes and ftp capabilities from this file.

//Includes
var gulp = require('gulp');
var fs = require('fs');
var fsPath = require('fs-path');
var mkdirp = require('mkdirp');


//Gulp plugin manager
 var plugins = require("gulp-load-plugins")({
     pattern: ['gulp-*', 'gulp.*', 'main-bower-files'],
     replaceString: /\bgulp[\-.]/
 });

//Define setup task
gulp.task('setup', function () {
    //get project layout object
    var json = JSON.parse(fs.readFileSync('projectSetup.json'));
    var paths = getPaths(json.fileTree || null);
    var templates = json.templates || null;
    var ignores = json.gitignore || null;

    //build file structure
    if (paths) {
        buildFileStructure(paths);
    }

    //build .gitignore
    if (ignores) {
        buildGitIgnore(ignores);
    }
   
    //populate base files
    if (templates) {
        buildBaseFiles(templates, paths);
    }
});


//Supporting Methods

/**
 * Loops through all template objects, finds the associated file path, and over writes the target file with the template
 * @param {object} templates 
 * @param {list} paths
 */
function buildBaseFiles(templates, paths) {
    for (var template in templates) {
        // skip loop if the property is from prototype
        if (!templates.hasOwnProperty(template)) continue;
      
        paths.forEach(function (path) {
            if (path.indexOf(template) > -1) {
                writeFileFromTemplate(path, templates[template]);
            }
        });
    }
}

/**
 * Creates files or folders according the paths passed in
 * @param {array} paths 
 */
function buildFileStructure(paths) {
    //Sort paths based on if they are files or folders
    paths.sort(function (a, b) {
        return (isFile(b) === isFile(a)) ? 0 : isFile(b) ? -1 : 1;
    });

    for (var path in paths) {
        var curPath = paths[path];

        //If the current path leads to a file, write the file path
        if (isFile(curPath)) {
            fsPath.writeFile(__dirname + '/' + curPath, "", function (err) {
                if (err) {
                    return console.log(err);
                }

                console.log("The file was saved!");
            })
        //if not, just make a folder
        } else {
            mkdirp(curPath, function (err) {
                if (err) { console.log(err) }
            });
        }
    }
}

/**
 * Finds the file defined in the path and overwrites it with strings in the content array
 * @param {string} path 
 * @param {array} contentArray 
 */
function writeFileFromTemplate(path, contentArray) {
    var content = "";
    for (var line in contentArray) {
        content += contentArray[line] + "\r\n";
    }
    fsPath.writeFile(__dirname + '/' + path, content, function (err) {
        if (err) {
            return console.log(err);
        }

        console.log("The file was saved!");
    });
}

/**
 * Builds the .gitignore file on the same file system level as this file
 * @param {array} ignores 
 */
function buildGitIgnore(ignores) {
    var content = "";
    ignores.forEach(function (ignore) {
        content += ignore + "\r\n";
    });
    fsPath.writeFile(__dirname + '/' + ".gitignore", content, function(err) {
        if (err) {
            return console.log(err);
        }

        console.log("The file was saved!");
    });
}

/**
 * Returns list of paths to be built in th file system
 * @param {Object} json 
 * @return {Array} pathArray
 */
function getPaths(json) {

    if (json == null) return null;
    var pathArray = [];
    for (var key in json) {
        // skip loop if the property is from prototype
        if (!json.hasOwnProperty(key)) continue;

        var obj = json[key];
        if (Array.isArray(obj)) {
            for (var x in obj) {
                pathArray.push(obj[x]);
            }

        } else if (obj == null) {
            console.log(key);
            pathArray.push(key);

        } else if (typeof obj == "object") {
            //console.log(key);
            var tempArray = getPaths(obj);
            for (var x = 0; x < tempArray.length; x++) {
                pathArray.push(key + "\\" + tempArray[x]);
            }
        }
    }
    return pathArray;
}

/**
 * Returns true if string contians a dot extension
 * @param {string} path 
 * @return {Bool} 
 */
function isFile(path) {
    return /\.[0-9a-z]+$/i.test(path);
}
  • Includes: Here you can see we are referencing the development packages we defined in step one. Require.js will automatically find them in the node_modules folder.
  • Gulp plugin manager: This is a handy tool that will be used in part 2 of this tutorial. In this step, we search for any node package that is prefixed with “gulp-”, strip the prefix off, and then load it into the plugins object. This keeps all our gulp plugins in one object.
  • Gulp setup: This is the main task that sets up the project structure. As you can see, we first read in the json object using the fs package and then send the various parts to our helper functions. In the first file when we defined gulp setup inside of the postInstall property, we were telling Node to run the setup command through Gulp.
  • Supporting Methods: We will not go into details about these as the names and purposes of them should be fairly intuitive.

Step 5: where do we stand now?

At this point, the final step is to watch it work. With your Angular application project folder select in your command window, enter the command npm install. At this point, the process will execute the following:

  1. Download the dev dependencies (defined in packages.json),
  2. Make sure gulp and bower are installed on your machine,
  3. Install bower packages (defined in bower.json),
  4. Run the gulp setup process (defined in gulpfile.js)
  5. Import the custom object
  6. Create the file structure
  7. Create the .gitignore file
  8. Overwrite blank files with templates

Once the process ends your project folder contents should look like this:

Angular_setup_file_structure

This is good start, but we’re not quite done getting everything ready to go. In part 2 we’ll cover compiling the bower package files into a usable script file for use by the index.html file, as well as how to automate that process during the installation.

ASP.NET Core and AngularJS – Part 2 – (Setup NPM, Bower, Gulp and IntelliSense)

[su_button url=”http://www.sigaostudios.com/2016/08/an-angularjs-in-net-core-journey-step-1/” style=”flat” icon=”icon: chevron-left”]Go back to Part 1 (Setup .NET Core)[/su_button]

In our last post, we walked through setting up Visual Studio 2015 to work with .NET Core and created an Empty ASP.NET Core solution. We are going to finish up phase 1 in this post and will have a completed framework to begin our next phase in which we will build an AngularJS application.

Phase 1 – Start at the start (Continued)

Phase1Post2

Add the Web Development Tooling

When you start with an empty solution, you will find we need to configure some helpful tools to improve our Web development workflow. These tools are Node Package Manager (NPM), Bower, Gulp and IntelliSense for JavaScript.

The following material will need to be updated soon, as the cogs of Microsoft’s development team continue to turn. Expect the following steps to become much easier in an upcoming release. For now, these are the steps you need to follow to configure this tooling.

Setup Node Package manager

NPM is a package manager for JavaScript. It allows you to easily add functionality to your project that will be integral as we move forward. If you haven’t already installed node.js, you will need to do it by downloading node and installing it from their website, here. If Visual Studio was open when you installed node.js, you will need to restart Visual Studio.

Once Node is installed, we need to do to add the package.json file. To do this, press Ctrl+Shift+A in our Project Solution Explorer and add a “npm Configuration File” and ensure it is named package.json.

Add npm Configuration File

You can learn more about the package configuration file here. The primary area you should focus on for what we are doing will be the devDependencies section. We will use this section to add some additional tools later on in this series. For now, here is what our package.json file looks like:

{
  "version": "1.0.0",
  "name": "angular sample",
  "description": "A sample application created for the Sigao Studios Blog",
  "private": true,
  { "license": "MIT" },
  "devDependencies": {
  }
}

Setup Bower

We will use npm to install our testing frameworks and similar tools. For our JavaScript packages such as AngularJS, Bootstrap or Moment, we will use Bower. To setup Bower, we will use the package manager console to build a default Bower file.

  1. Click Tools -> Nuget Package Manager -> Package Manager Console
  2. Type npm install -g bower
    • This command will install Bower globally.
    • Restart Visual Studio.
      Use NPM to Install Bower
  3. While we are waiting for Visual Studio to come back up, we can use Bower Init to initialize our Bower configuration. To do so, we will need to open a node.js command prompt (a shortcut was added when you installed node.js).
  4. You will need to change directories to the root of your AngularSample.Web project.
  5. Once you are in the root, type bower init.
  6. Provide the following responses when prompted
    • Name: We used AngularSample.Web. This is the name of your application.
    • Description: A description of your application.
    • Main File: We used index.html.
    • Keywords: A list of keywords that describe your solution
    • Authors: Who wrote the application?
    • License: The Default is MIT. We use that for our open source and demo code. Enter the license you adopt for your code.
    • Homepage: We used the Sigao Studios page.
    • Set currently installed components as dependencies: Y
    • Add commonly ignored files to ignore list? Y
    • Would you like to mark this package as private which prevents it from being accidentally published to the directory? Y
      Run Bower Init
  7. Once you finish responding, the Bower tool will create a bower.json file and store it in the current directory. When you return to Visual Studio, you are now ready to begin using Bower.

When you return to Visual Studio, you won’t see your bower.json file listed in the solution explorer. That’s because it is hidden by default. To show it, you will need to select the Show All Files option in the solution explorer toolbar.

Bower.json In Visual Studio
Bower.json In Visual Studio

Now, let’s add a .bowerrc file to let Bower know where to install our packages.

  1. Add a new file to our project called “.bowerrc”
  2. In order to have Bower install packages in the “wwwroot/lib” folder, add the following code:
    {
      "directory": "wwwroot/lib"
    }
    

Finally, here is the bower.json file we created.

{
  "name": "AngularSample.Web",
  "description": "A sample application for Sigao Studios Blog",
  "main": "index.html",
  "keywords": [
    "Sample",
    "Application",
    "Bower",
    "AngularJS",
    ".NET",
    "Core"
  ],
  "authors": [
    "Chris Sims"
  ],
  "license": "MIT",
  "homepage": "www.sigaostudios.com",
  "private": true,
  "ignore": [
    "**/.*",
    "node_modules",
    "bower_components",
    "test",
    "tests"
  ]
}

We will come back to this in a little bit and add several JavaScript libraries, but for now, let’s continue on to Gulp.

Setup Gulp

Gulp JavaScript task builder that is extremely helpful at processing your site content before serving. You can use it to compile SASS or LESS, minify your JavaScript and bundle your files together. You do this by creating a series of tasks that are defined by JavaScript. These tasks can be kicked off manually, or linked to events in Visual Studio such as “Pre-build”, “Post-build” or “Project Open.” To install Gulp, we will use npm and the package.json file.

Open your package.json file and the following dependencies to your devDependencies list.

{
  "version": "1.0.0",
  "name": "angular sample",
  "description": "A sample application created for the Sigao Studios Blog",
  "private": true,
  { "license": "MIT" },
  "devDependencies": {
    "gulp": "3.8.11",
    "gulp-concat": "2.5.2",
    "gulp-cssmin": "0.1.7",
    "gulp-uglify": "1.2.0",
    "gulp-less": "^3.1.0"
  }
}

Now that the framework is in place, we need to add a gulpfile.js to our project.

Visual Studio - Add Gulp FIle

  1. Right click on the project in your Solution Explorer and click Add->New Item.
  2. Expand .NET Core and select Client-Side to view client side templates.
  3. Select the Gulp configuration file.

Your gulp file is pretty basic at the moment. It has no tasks and, for the moment, we will leave it that way. There is a lot to gulp, and we will explore that soon. For now, you can see a list of great gulp recipes here.

Setup IntelliSense

Now, one last thing before we get into some actual code. Let’s make sure we leverage the power of Visual Studio’s IntelliSense functionality for this project. In an empty project, the file necessary to make IntelliSense work is missing. We need to add it.

  1. Right click on the project in your Solution Explorer and click Add->New Item.
  2. This time, select the JavaScript file template.
  3. Name the file _references.js

Now, the last step in making IntelliSense work is to add the appropriate references to the references file. These reference directives tell IntelliSense where to look to get the information it needs to work. You specify a reference using the following syntax:

/// <reference path="wwwroot/lib/adal-angular/lib/adal.js" />
/// <reference path="wwwroot/lib/adal-angular/lib/adal-angular.js" />
/// <reference path="wwwroot/lib/angular/angular.js" />

You can automatically add these references using an autosync feature.

Visual Studio - References file for IntelliSense

  1. Right click on the _references.js file in the solution explorer.
  2. Click Auto-sync javascript references.
  3. Right click on the _references.js file in the solution explorer.
  4. Click Update JavaScript references.

Now, our _references.js file looks like this:

/// <autosync enabled="true" />
/// <reference path="gulpfile.js" />

So, we have configured npm, Bower, Gulp and IntelliSense. Let’s get into some actual code.

Setting up .NET Core as a FileServer

When we finished our last post, we had a very basic ASP.NET Core solution that would serve up the simple text, “Hello World!” ASP.NET Core gives you a lot of flexibility to configure how your application handles requests. Let’s look at Startup.cs and see how we can leverage that flexibility.

Startup.cs

The startup.cs file is the entry point to the application. It allows you to configure request pipelines, setup services and much more. We won’t go into details here, for more information on startup.cs, check out the ASP.NET Core documentation here.

Our startup.cs file looks like this:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

namespace AngularSample.Web
{
    public class Startup
    {
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
            loggerFactory.AddConsole();

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.Run(async (context) =>
            {
                await context.Response.WriteAsync("Hello World!");
            });
        }
    }
}

I’ve highlighted the code that configures the application to respond with “Hello World!” We can add multiple service handlers, or roll our own, that instruct our application in how to handle requests. We will use the Static File Server functionality to host a very simple Web server for our demo application. To do that, we need do the following:

  1. Begin by removing lines 31-34 of startup.cs to stop it from responding with “Hello World!”
  2. Next, we must configure our Middleware to serve static files.
    1. Middleware are components that actually handle requests and responses. You can learn about Middleware here.
    2. Locate the Configure method in your startup.cs.
    3. Immediately after loggerFactory.AddConsole(); add app.UseStaticFiles(); to that method.
    4. You should see a red squiggly line under the code you just added. You will need to add the package “Microsoft.AspNetCore.StaticFiles“. To do so, hover over the line of code you just added, when you see a light bulb button popup underneath that, click it and then click “Add package Microsoft.AspNetCore.StaticFiles
      Visual Studio - Add Static Files
    5. Finally, let’s instruct our application to serve up “default files.” Default files are files with the name Default.htm(l) or Index.htm(l). If we don’t instruct our application to respond using Default Files, we will have to specify our file name in the request string (http://localhost:5000/index.html instead of http://localhost:5000/)
    6. To do so, simply add app.UseDefaultFiles(); immediately before app.UseStaticFiles();

Our startup.cs file should now look like this:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

namespace AngularSample.Web
{
    public class Startup
    {
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
            loggerFactory.AddConsole();

            app.UseDefaultFiles();
            app.UseStaticFiles();

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
        }
    }
}

If we run our app now, it will serve up any file located in the wwwroot directory of our application. I encourage you to review the ASP.NET Core documentation on serving static files to learn more. You can access that documentation here.

Now that we have our file server ready to go, let’s create a file to serve.

Use Bower to install the base packages

Before we go further, let’s add a few key JavaScript packages to our project. We will start with the following libraries:

  • jQuery
  • HTML5 Boilerplate
  • Bootstrap
  • Angular

To install these, we will use Bower.

  1. Open your Bower.json file (if you can’t see it, be sure to select the “show hidden files” option in your solution explorer).
  2. Add the following code just before the closing }
      , 
    "dependencies": {
        "jquery": "2.2.3", 
        "html5-boilerplate": "^5.3.0",
        "bootstrap": "3.3.6",
        "angular": "1.5.8"
    }
    

Our bower.json file should now look like this:

{
  "name": "AngularSample.Web",
  "description": "A sample application for Sigao Studios Blog",
  "main": "index.html",
  "keywords": [
    "Sample",
    "Application",
    "Bower",
    "AngularJS",
    ".NET",
    "Core"
  ],
  "authors": [
    "Chris Sims"
  ],
  "license": "MIT",
  "homepage": "www.sigaostudios.com",
  "private": true,
  "ignore": [
    "**/.*",
    "node_modules",
    "bower_components",
    "test",
    "tests"
  ],
  "dependencies": {
    "jquery": "2.2.3",
    "html5-boilerplate": "^5.3.0",
    "bootstrap": "3.3.6",
    "angular": "1.5.8"
  }
}

When we save the bower.json file, Bower automatically begins loading the requested dependencies and storing them in the folder “wwwroot\lib.” Once that completes, our solution explorer should now look like this:

Visual Studio - Solution Explorer After Bower Run

Create a base index.html

Finally, let’s create a simple index.html based on the HTML5 Boilerplate template in order to confirm that our solution is working.

  1. Create a new file in our project under the wwwroot directory by right clicking on the wwwroot directory in solution explorer, and clicking “Add -> Add new item”
  2. Select the HTML Page template and call the file “index.html”
  3. Use the following code for your index.html file
<!doctype html>
<html class="no-js" lang="">
<head>
    <meta charset="utf-8">
    <meta http-equiv="x-ua-compatible" content="ie=edge">
    <title>Sigao Studios - Angular Sample</title>

    <meta name="viewport" content="width=device-width, initial-scale=1">

    <link rel="stylesheet" href="lib/html5-boilerplate/dist/css/normalize.css" />
    <link rel="stylesheet" href="lib/html5-boilerplate/dist/css/main.css" />
    <link rel="stylesheet" href="lib/bootstrap/dist/css/bootstrap.css" />

    <script src="lib/html5-boilerplate/dist/js/vendor/modernizr-2.8.3.min.js"></script>
</head>
<body>
    <!--[if lt IE 8]>
        <p class="browserupgrade">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</p>
    <![endif]-->
    <div class="container">
        <div class="page-header">
            <h1>Hello world!</h1>
        </div>
        <div class="well">
            <p>
                The true sign of intelligence is not knowledge but imagination. <b>-Albert Enstein</b>
            </p>
        </div>
    </div>
    

    <script src="lib/jquery/dist/jquery.js"></script>
    <script>window.jQuery || document.write('<script src="lib/jquery/dist/jquery.js"><\/script>')</script>
    <script src="lib/html5-boilerplate/dist/js/plugins.js"></script>
    <script src="lib/html5-boilerplate/dist/js/main.js"></script>
    <script src="lib/bootstrap/dist/js/bootstrap.js"></script>
    <script src="lib/angular/angular.js"></script>
    </body>
</html>

Once you save your index.html file, press F5 to start debug mode. When it runs, you should see the following:

Angular Sample Running - Phase 1 Complete
Angular Sample Running – Phase 1 Complete

Conclusion

We have now configured a full toolbox of modern tooling with which to build our Angular Sample application in ASP.NET Core. In the next phase, we will focus on AngularJS, and build an Angular application that follows the appropriate coding standards and best practices for Angular. From there, we will configure a WebAPI middle tier, and will then explore running those applications inside Docker containers. For now, play around with your app, explore adding other Bower packages, or read about Gulp. And if you have any questions, feel free to reach out to us using our contact page or comment on this post.

An AngularJS in ASP.NET Core Journey – Part 1 (Setup Visual Studio and .NET Core)

I’ve considered a lot of options for our first Sigao Studios blog post. And while there are many great options, I wanted to start with a series on creating a modern Web application using AngularJS and .NET Core. This guide will be designed for beginners and will walk through step by step a long journey to creating a complex application that uses plenty of cool technologies such as AzureAD, Docker and others.

Phase 1 – Start at the start

We will end Phase 1 with a fully configured development environment and workflow that will allow you to quickly develop your AngularJS Single Page Application (SPA).

Intro to AngularJS and .NET Core Phase 1 Outline


So, as Lao Tzu once said, the journey of a thousand miles begins with one step. At the end of this, we will have configured Visual Studio 2015 to work with .NET Core and we will have created a blank .NET Core Solution.

These are entry level steps. If you are ready to get your feet wet, then go on to the next post where I will cover setting up tools such as Bower and Gulp and will get started with a good, core HTML framework that will be the basis of our next phase.

Configure Visual Studio

Configure Visual Studio

We will use .NET Core 1.0 to host our demo application. .NET Core is a cross platform development platform developed by Microsoft and members of the .NET Community. .NET Core allows you to be operating system agnostic. Code that you write to host an MVC page or cool new dashboard tool can run on Windows, Azure, Linux, or MacOS (among others). .NET Core gives you the power of the .NET framework with revolutionary portability. We will leverage that portability in this series. We start by running our code on a Windows box, but will eventually learn how to run it in Linux, both in and out of Docker.

For now, let’s get the development environment setup. I will be using Visual Studio 2015 Community Edition. If you don’t already have that, then get it. It’s free and is extremely powerful. Go to www.visualstudio.com and download Community 2015.

If you already have Visual Studio, be sure to follow Microsoft’s prerequisites guide located here.

Once you get Visual Studio 2015 installed, you will need to get .NET Core Tooling Preview 2 for Visual Studio 2015. The .NET Core Tooling gives you the project templates and tools needed to allow Visual Studio to create and maintain .NET Core projects.

Create a blank .NET Core Application

Create a Blank Solution

Now, before I start any project, I like to create a blank solution that will hold all of the projects I’m going to build. This allows me to get a clean folder structure to work with and is helpful in large, multi-project solutions.

Create the solution

Visual Studio -> Create Blank Solution
How to create a blank solution in Visual Studio 2015
  1. Start Visual Studio 2015.
  2. Click File -> New -> Project.
  3. Search for “Blank Solution” using the search box in the top right of the dialog.
  4. Select Blank Solution.
  5. Give your solution a name. We will be using AngularSample.
  6. Ensure you have “Create directory for solution” selected.
  7. You can create a Git repository if you so chose, for now, we will skip that step.
  8. Click OK

Create the project

ASP.NET Core gives you several options of templates to work with. You can begin with an empty project, or elect to start with an MVC or WebAPI solution. Since we will be focusing on building client-side, Single Page Applications, we will start with a blank solution for now. Later on, we will explore other options, but I want to start with a blank slate and build out our modern web development tooling environment from the ground up.

Now that we have a blank solution to group all of our work into, let’s add our first project. We will call it AngularSample.Web to indicate that this is the web front end. In the future, we will add an API project, so this naming convention will help us organize our files.

Visual Studio -> Create Base .NET Core Project
How to create an ASP.NET Core project
  1. Press Ctrl+Shift+N to create a new project, or File -> New -> Project.
  2. In the templates, expand Visual C# and select .NET Core.
  3. Select the ASP.NET Core Web Application (.NET Core) template.
  4. Give your project a name, we are using AngularSample.Web.
  5. Ensure “Add to solution” is chosen from the Solution drop down.
  6. For now, uncheck “Add Application Insights to project” later on we will likely explore Application Insights, but we will skip this for now.
  7. Click OK
Visual Studio -> New Asp.NET Core Template
ASP.NET Core Template selector

Finally, we will select the Empty template. In later posts, we will look at Web API and Web Application, but for now, we want a bare bones ASP.NET project.

Visual Studio Empty .NET Core Project
An empty ASP.NET Core Project

Now, we have a blank ASP.NET Core solution. We will run it using the .NET Core runtime. To do that, we must tell it to Debug using “AngularSample.Web”.

Visual Studio -> Run In ASP.NET Core

Finally, if we press F5 the solution will run in .NET Core as shown here.

Empty ASP Net Core Running

It’s not very impressive, but then again, we haven’t done that much. We have a base canvas to begin molding. In the next post, we will learn how to add NPM, Bower, Gulp, Grunt and JavaScript IntelliSense to the solution to leverage the power of modern Web development tooling. From there, we will get a base application setup and then, finally, get into doing some cool things with AngularJS.

[su_button url=”http://www.sigaostudios.com/2016/08/aspnet-core-and-angularjs-step-2/” style=”flat” icon=”icon: chevron-right”]Continue to the next post[/su_button]