Sprint Planning in Visual Studio Team Services

Sprint Planning in VSTS

Derived from photo by Dafne Cholet / flickr.com, CC BY

Getting started in Visual Studio Team Services (VSTS) eventually leads to planning a sprint. This post discusses how to configure a sprint in VSTS and schedule work for this iteration.

This is one of a series of posts detailing the process of building an application with Angular, Visual Studio, ASP.NET Core, and Azure. See the complete list of posts here.

This is a summary of decisions made and lessons learned while creating this project in Visual Studio Team Services (VSTS):

  • Chose two weeks for the initial sprint duration and because I am a team of one, I may have varying sprint durations in the future to fit my schedule. While VSTS supports varying sprint durations, teams generally operate better with a consistent schedule.
  • Set the sprint capacity to later compare to scheduled work. Although VSTS capacity is set per day in hours, this number can be calculated from week-based or sprint-based capacity estimations.
  • Estimated backlog items using a modified Fibonacci sequence, roughly based on hours to start but will be used to comparatively size future product backlog items.
  • Estimated tasks in hours and added the Original estimate and Completed work fields to the task work item template for tracking this information as well.
  • Verified the scheduled work against the configured capacity and adjusted the scheduled work to fit the sprint capacity.

Configure the Sprint

The first thing to determine is the duration of sprints. If working on a large team, predictable sprint durations are helpful to keep everyone on the same page. However, for a project with one developer, I am going to determine sprints more on my own availability. I have been working recently in two-week increments, but alternating these iterations between code-related projects and other personal projects. So, while I may have a sprint that lasts two weeks, I may not schedule the next sprint until two weeks after the end of the previous. Also, I try to squeeze in a "week off" to my schedule occasionally where I try not to focus on achievement but rather rest and spend time with friends and family. The point is that while large teams may benefit from predictable sprint durations, Visual Studio Team Services allows for flexible durations if that works better for you and your team.

To set the dates, go to the Work section of the team project. VSTS provides a default list of iterations named Sprint 1, Sprint 2, etc. Choose Sprint 1 to view the page for that iteration. Look towards the top right of the screen and you will see a link to Set dates. Click that link and this dialog appears:

Edit iteration dialog

Set the start and end date for the sprint. Optionally, change the sprint name. I decided to go with sprint names that correspond to famous jazz musicians of the bebop era. Press Save and close to save the sprint.

Tip: The Iteration settings are also available from the Settings menu in the top navigation. Select Work, then Iterations to modify the full iteration list.

Full iteration list

Set Capacity

Capacity is another tool for scheduling work. By setting the capacity for people working on the project (even if only yourself), it helps determine if the team is committing to too much or too little work for the sprint. The VSTS sprint burndown chart also uses this number to visualize progress.

The first step is to determine how many hours per day or week everyone can commit to the project. I have roughly 14 hours per week to devote during this sprint. On the page for the current sprint, select the Capacity tab:

Capacity tab

Enter the capacity per day. Since I can do 14 hours per week, I entered in 2 hours per day. This field allows for decimals to accommodate the daily number for any week-based or sprint-based capacity estimations. For instance, if a teammate could only work 20 hours for the entire sprint, divide 20 hours by the number of days in the sprint (14) to arrive at a daily capacity of 1.43.

By default, VSTS does not count weekends as working days. Being a personal project, the weekends are prime time for getting things done so I wanted them to count towards the capacity. To enable them, click on the gear/settings icon in the top right of the team's work page and then find the settings for Working days. Enable the checkboxes for those days to include them in the capacity.

Working days settings

Estimate Product Backlog Items and Tasks

To improve my estimation skills, I'm estimating my work in VSTS. This isn't entirely necessary but I find tracking this over time leads to a better understanding of what can be accomplished in each sprint. I use two different estimation systems for product backlog items and tasks.

For product backlog items, I like using a modified Fibonacci sequence like what's found on a planning poker deck. The modified sequence progresses as 0, 1/2, 1, 2, 3, 5, 8, 13, 20, 40, 100, etc. The product backlog item estimates do not reflect hours, but are sized relative to each other. I happen to use hours as a baseline when starting out. For instance, because this is my first sprint and first estimates, the three backlog items estimated equal 24 (8 each). This is roughly equivalent to my sprint capacity which is 28. This can be confusing for some because the units of measure are close (sizing versus hours) but not the same. I like having that loose association but I must remember that when estimating backlog items, I'm thinking about how they compare to other backlog items, not how many hours they will take. For instance, if I start thinking that a backlog item is 10 hours, I would force myself to estimate it as either an 8 meaning that it is roughly equivalent to the amount of work done for a complete product backlog item or I would decide that it is indeed larger and estimate at 13 which is the next largest number in the modified Fibonacci sequence.

Once the backlog items have been estimated, choose one or more for the sprint backlog by setting the sprint property in the product backlog item itself. I decided to take one product backlog item off my product backlog and added two new ones to the sprint and estimated them. The two new backlog items represent blog posts discussing the project work.

Once I have the backlog items that I think I can accomplish during the sprint, I start to break them down into tasks. These tasks are estimated in hours which will be matched to the sprint capacity. By default, the scrum process template in VSTS gives one field for task estimation, Remaining Work. This field is used to calculate the burndown chart as the sprint progresses. I decided to also add the Original estimate and Completed work fields to my task work items to get a better understanding of how well (or not) I estimate a task. These fields already exist in VSTS and simply need to be added to the work item template. This documentation provides details on customizing work items. Be sure to assign each task to yourself or the person scheduled to implement the work during the sprint. Look at the board view for the sprint and this is how each backlog item appears:

Product Backlog Item on Kanban board

One final thing to do before finalizing the sprint plan is to check the capacity screen one more time. On the right-hand side, there are bullet graphs representing each team member's capacity and the amount of work scheduled for them. If the bars are green, you are good to go. If they are red, it means an individual has more estimated work than capacity and you should consider adjusting the workload.

Capacity Screen

Get to Work

Now it's time to get started working through the sprint backlog. Use the Kanban board to easily visualize the sprint work. As work is accomplished, update each task with the time remaining and time completed.

Finally, refer to the sprint burndown chart to see if you are on track to reach your goals. Happy coding!

Creating a Project in Visual Studio Team Services

Starting a Personal Project in Visual Studio Team Services

Derived from photo by Ignacio Palomo Duarte / flickr.com, CC BY

This is one of a series of posts detailing the process of building an application with Angular, Visual Studio, ASP.NET Core, and Azure. See the complete listing of posts here.

This is a summary of decisions made and lessons learned while creating this project in Visual Studio Team Services (VSTS):

  • VSTS is free for teams up to 5 users
  • Started with a backlog to outline ideas for the application
  • Only entered items related to the first milestone which is a minimum prototype to validate the application's usefulness
  • Chose Git source control for my VSTS project because of personal preference and because it will be easier to publish the source code publicly to GitHub while maintaining day-to-day work in VSTS
  • Chose the Scrum process template for the VSTS project because the work item flow is slightly simpler given that I am both the developer and the user
  • Created Feature work items for items that, when complete, demonstrate value to the user
  • Created Backlog Item work items for items that benefit the engineering or design process

Creating the Project in Visual Studio Team Services

First, understand that Visual Studio Team Services (VSTS) is free for teams of up to five developers (and unlimited for work item access). This includes free private source control repositories, agile work management, build credits, and more. Check out all the free stuff here.

In VSTS, I created a new project named Bebop. There are two main decisions to make when starting the project, the type of source control to use and the work item template. I chose Git source control because I have grown to really like the ease at which I can create branches and work with multiple repositories. For instance, even though the source code will primarily live privately in VSTS, I will post it publicly to GitHub and Git makes it easy to distribute in this way.

For the process template, I chose the Scrum template. The work item status flow requires slightly less steps which is preferable given that I am the developer and customer at this point. Also, I prefer the terminology of Backlog Item over User Story for organizing work. As a developer, there are many times where system changes are made for performance or security reasons and I find writing user stories such as "As a 'user', I expect my software to be secure…" unnecessary. There are dozens of different ways to approach this configuration so do what's best for your team and project. Here is more information regarding the various process templates built-in to VSTS.

Creating the Backlog

Upon developing the backlog, I started the list in OneNote and then later moved it to Visual Studio Team Services (VSTS). It doesn't really matter the tool when starting, the initial backlog is simply a list of items that need to get done. I also thought of a couple milestones and only added items related to the first. The first milestone is to deliver the minimum feature set that can prove whether my idea for the app will even work in real-world usage. The initial list of backlog items is specific to this goal.

When brainstorming the items, there were two large categories in mind. The first category relates to which items I need to put in place to deliver the demo application. These are things like source control, deployments, etc. I also included in the list to create a prototype design. Before writing any code, it helps to take the initial bucket of features and mock out the user interface and interaction design to help avoid designing into a corner during coding. For these items, I created a Product Backlog Item work item.

The second category of backlog items were the actual features themselves. For these items, I create a Feature work item. Don't worry if you decide to use the work item types differently later as you can change the type if needed. I like to be granular when breaking down features and functionality on the backlog. While there are no deadlines, per se, estimating and tracking these work items is valuable for developing estimation skills and smaller backlog items help enable better estimations. There are other insights that VSTS will give based off these estimations such as a burndown chart for each sprint.

For now, I focused on getting the work into the system which amounts to nothing more than filling out the title of the work item. It will be an ongoing process to refine the list and further schedule it for implementation. This is what the initial list looks like in VSTS:

Backlog Screenshot

In the next post, I'll look at how I'm going to schedule this work in VSTS and organize it into sprints. The process of creating a backlog in VSTS is simple yet there are subtle decisions to make in organizing the work. What are your preferences for creating a backlog in VSTS?

Introducing Project Bebop

Introducing Project Bebop

Derived from photo by Loren Kerns / flickr.com, CC BY

Today starts a new journey on angularfirst.com. Welcome to Project Bebop.

Going forward, each post will detail successes and challenges using Angular, Visual Studio, ASP.NET Core, and Azure in the context of a real application. Being a side-project, helmed by one developer who is also the primary customer, this won't reflect all the considerations of an enterprise application. However, where possible, I will use enterprise-grade development techniques during development.

The goal is that you will gain insight into the benefits and challenges of adopting new technologies and techniques in Angular, Visual Studio, ASP.NET Core, and Azure. More importantly, you will see how these pieces fit together. This is the area that I find the most interesting and plan to focus on these integrations. Developers can't always start from a blank slate and are forced to adopt technologies in an unconventional and/or incremental way with their existing code base. I will get to cover these tradeoffs with examples that you can see in real-time.

The project itself is a personal take on a To-Do application. I'm surprised that given the amount of To-Do applications on the market, I still end up falling back to tools like OneNote and Excel to organize my life. So, I'm going to build one for my own needs and the goal is that anyone else who finds it interesting will be able to use it too.

To be clear, though, the primary goals are learning and sharing. This is an exercise in product development for the lone developer and I'm looking forward to sharing the journey.

This is the list of blog posts related to the project:

The NgModule ‘forRoot()’ Convention

The NgModule forRoot Convention Hero Image

Derived from photo by Boris Tassev / flickr.com, CC BY-SA

The NgModule forRoot() convention is a curious one. The naming explains how to use it but not what it is or more importantly why it's necessary to import an NgModule in this way.

This post peeks beneath the API to help you understand this design and get the most out of the convention.

The NgModule forRoot() Convention

There comes a point when developing in Angular when an NgModule requires a call to its forRoot() method when importing. The most notable example of this is with the RouterModule. When registering this module at the root of an Angular application, importing the RouterModule looks like this:

import { RouterModule, Routes } from '@angular/router';

const routes: Routes = [
    { path: '',   redirectTo: '/index', pathMatch: 'full' }
];

@NgModule({
  imports: [
    RouterModule.forRoot(routes)
  ],
  ...
})
export class AppModule { }

This convention is also used in ngx-bootstrap and was previously used in Angular Material. The convention implies that a given module must be registered with the root NgModule of an application while invoking the forRoot() method. What is so special about this method that it needs to be called at the root of an application as opposed to any other NgModule?

For starters, what does the forRoot() convention return? Generally, the return type for this method is an object conforming to the ModuleWithProviders interface. This interface is an accepted NgModule import and has two properties:

interface ModuleWithProviders { 
  ngModule: Type<any>
  providers: Provider[]
}

Put simply, the forRoot() method returns an NgModule and its provider dependencies. What does this have to do with the root NgModule? Maybe nothing. In fact, while this convention implies that it must be imported at the root of the application, in many cases you can import it in a non-root NgModule and it will work – GASP!

Putting that aside for a moment, this is how the ModalModule in ngx-bootstrap uses the forRoot() convention:

import { NgModule, ModuleWithProviders } from '@angular/core';

import { ModalBackdropComponent } from './modal-backdrop.component';
import { ModalDirective } from './modal.component';
import { PositioningService } from '../positioning';
import { ComponentLoaderFactory } from '../component-loader';

@NgModule({
  declarations: [ModalBackdropComponent, ModalDirective],
  exports: [ModalBackdropComponent, ModalDirective],
  entryComponents: [ModalBackdropComponent]
})
export class ModalModule {
  public static forRoot(): ModuleWithProviders {
    return {ngModule: ModalModule, providers: [ComponentLoaderFactory, PositioningService]};
  }
}

Notice how the ModalModule does not declare any providers in the @NgModule decorator but does so in the static forRoot() method.

Why is the Root NgModule Important?

Even though importing the additional providers of the forRoot() method theoretically works in child NgModules, registering it at the root of the application helps in a number of ways.

First, consider how Providers are injected differently than components and directives. Typically, when decorating a class with @Injectable and registering as a provider in an NgModule, this class is created once and that one instance is shared amongst the entire application. When Angular bootstraps the root NgModule, all available imports in all NgModules are registered at that time and made available to the whole application – they are global. This is why providers registered in a child NgModule are available throughout the whole application.

Components and directives on the other hand are instantiated multiple times, once per instance in the markup. In addition, these items are scoped to the NgModule in which they are imported to prevent naming conflicts where two components might have the same selector for example. Because of this difference in dependency injection (DI) behavior, the need to differentiate an NgModule containing components and directives from a ModuleWithProviders containing components, directives, and providers is helpful which is where the forRoot() method makes that distinction.

Dependency injection, however, doesn't always work this simply. There are times when all the application's NgModules are not available during the bootstrap process. Lazy-loading is such an example. When lazy-loading an NgModule during routing, the providers registered in the lazy-loaded NgModule and its children aren't available during the bootstrap process and Angular is unable to register them at that time. Therefore, they are added as providers only when the route is loaded and furthermore they are scoped to be injected starting at the lazily-loaded NgModule and its children. If there are multiple lazy-loaded NgModules attempting to register the same providers, each of these nodes of the NgModule tree end up with different instances. By importing the providers at the root, it helps ensure that all lazy-loaded NgModules get the same instance of the provider and is why forRoot() is named as such.

Be sure to read more about the nuances of Angular's dependency injection in the documentation.

When to Use the forRoot() Convention

As a consumer, use it when a library dependency requires it. Import the module at the root of the application and register with the forRoot() method to import the providers globally. In other NgModules, use the appropriate non-root form of the import when necessary to import the components and directives.

In the case of both Angular Routing and ngx-bootstrap, this convention helps share providers amongst multiple instances of directives and components to achieve a global concern for the application. For example, ngx-bootstrap uses this convention for the modal dialog component. While there may be many modal instances defined in the markup of an application, the modal takes over the entire UI hence all instances of the dialog should understand how they affect this global concern.

In the case of routing, there is only one window.location for the application so even though there may be child routes and various instances of router-outlet components, they all need that one global dependency of the window's location so that they can work together.

In both cases, the consumer of the modal dialog or router does not need to know how these items communicate and manage shared concerns. In this way, the forRoot() method abstracts away the necessary provider registration.

In short, consider using the convention when you have multiple custom components or directives that all take a dependency on a global UI concern and need to work together to manage this global state. To be clear, the forRoot() convention is a form of coupling which should only be used after careful design consideration.

It's best to avoid using this convention with third-party libraries. For instance, don't try to bubble up all the NgModule dependencies of the application using this convention. The providers returned by the forRoot() method should be internal dependencies that work exclusively with the other components included in the ModuleWithProviders. Third-party dependencies should be treated like npm peerDependencies and imported and registered in the root NgModule directly so that other components can more easily share the same dependencies and help ensure all consumers reference the same package version when npm versioning resolves.

Takeaways

In summary, the forRoot() convention represents a way to import an NgModule along with its providers using the ModuleWithProviders interface.

When a feature NgModule exports components and directives that require sharing the same custom provider instances, consider registering these providers in the root NgModule with a forRoot() method. This can help ensure that all child NgModules have access to the same provider instances without requiring the consumer to handle the provider registration explicitly.

For more information on implementing the forRoot() convention, there are some additional implementation ideas found in the Angular documentation.

Please leave a comment below sharing your experiences using the forRoot() convention.

When to Use ES2015 Modules Instead of Angular Dependency Injection (and When Not to)

When to Use ES2015 Modules Instead of Angular Dependency Injection Title Image

Derived from photo by fdecomite / flickr.com, CC-BY

This post discusses some of the nuances between ECMAScript 2015 module dependencies and Angular's dependency injection system. These are design considerations and while you may decide not to use the approaches discussed, the goal is to provide you with a context in which to make more thoughtful decisions about how to use dependencies throughout your Angular application.

A Tale of Two Dependency Systems

When building an Angular application, there are two main dependency systems at play. The first is EcmaScript 2015 (ES2015) modules. This is the system used when creating an import statement or exporting an object. This system uses string identifiers to obtain dependencies via URL or npm package name.

import { platformBrowser } from '@angular/core';

The other dependency system is Angular's dependency injection (DI) system which is built on top of the ES2015 module system. Unlike the static nature of ES2015 dependencies, these dependencies are configurable when the application bootstraps. They are typically defined as a provider in an NgModule.

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule
  ],
  providers: [
    ShoppingCartService
  ],
  bootstrap: [ 
    AppComponent 
  ]
})
export class AppModule {

}

While not entirely a one-to-one relationship, consider the idea that ES2015 module dependencies are hard dependencies meaning they cannot easily change upon running the application. On the other hand, Angular provides a more loosely-coupled dependency structure that is more easily configured at runtime.

Note: There are in fact more than two dependency mechanisms if you consider npm module resolution where version numbers can influence the resolution of ES2015 modules or a bundler like webpack which can conditionally swap ES2015 dependencies based on configuration. This would be tooling-based configuration whereas this post focuses on code-based configuration.

Angular Dependency Injection (DI)

At a high level, Angular reads the NgModule metadata during the bootstrap process and creates an injector capable of providing these dependencies through the class constructor of components and services throughout the application. Please read more about Angular's dependency injection in the documentation to understand the full details. This post refers to Angular dependency injection at a high level.

To look at an example, consider an e-commerce application with a digital shopping cart. Imagine a mini-view of the cart while the user is browsing product pages and a separate, detailed view when it's time to check out. The logic to calculate the quantity of items in the cart is the same for each view. Therefore, both pieces of the UI may depend on a ShoppingCartService to calculate the total quantity of items in the cart. This service is provided to the components through dependency injection.

shopping-cart.service.ts

import { Injectable } from '@angular/core';
import { CartDetail } from './shopping-cart.model';

@Injectable()
export class ShoppingCartService {
  getTotalQuantity(cartDetails: CartDetail[]): number {
    if (!cartDetails) {
      return null;
    }

    const total = cartDetails.map(carDetail => carDetail.quantity)
      .reduce((previous, current) => previous + current, 0);

    return total;
  }
}

shopping-cart.component.ts

import { Component } from '@angular/core';
import { CartDetail } from './shopping-cart.model';
import { ShoppingCartService } from './shopping-cart.service';

@Component({
  selector: 'app-shopping-cart',
  templateUrl: './shopping-cart.component.html'
})
export class ShoppingCartComponent {

  shoppingCart: CartDetail[] = [
    { productName: 'Hammer', quantity: 1 },
    { productName: 'Purple Shorts', quantity: 26 },
    { productName: 'Web Shooter', quantity: 2 }
  ];

  totalCartQuantity = this.shoppingCartService.getTotalQuantity(this.shoppingCart);

  constructor(private shoppingCartService: ShoppingCartService) { }
}

Consider the number of steps involved in registering and using this dependency in a component through Angular's DI:

  1. Create the ShoppingCartService class
  2. Import and decorate the dependency with the @Injectible() decorator
  3. Import the dependency into the appropriate NgModule
  4. Register the service as a provider
  5. Import the dependency in the component's ES2015 module
  6. Add it as an argument in the component's constructor
  7. Use the dependency

That's quite a bit of code to implement the default DI recommendation. This isn't a criticism, just an observation. Because this implementation uses the ES2015 module standard and includes the added TypeScript benefits, these steps are reasonable in pursuit of loosely-coupled dependencies.

Note: The Angular CLI can help you avoid having to write some of this code by hand.

While Angular's dependency injection implementation comes with many benefits, it's worth considering an alternative.

Using ECMAScript 2015 (ES2015) Module Dependencies

Instead of creating a class and registering it with an NgModule, consider writing a more generic piece of code that can map and calculate a total from an array of objects. Create a function called mapArraySum in its own ES2015 module. Look at the steps for using this function in a component:

  1. Create the mapArraySum function
  2. Import the dependency in the component's ES2015 module
  3. Use the dependency

mapArraySum.ts

export function mapArraySum<T>(array: T[], mappingFunc: (item: T) => number): number {
  if (!array) {
    return null;
  }

  const total = array.map(mappingFunc)
    .reduce((previous, current) => previous + current, 0);

  return total;
}

shopping-cart.component.ts

import { Component } from '@angular/core';
import { CartDetail } from './shopping-cart.model';
import { mapArraySum } from './mapArraySum';

@Component({
  selector: 'app-shopping-cart',
  templateUrl: './shopping-cart.component.html'
})
export class ShoppingCartComponent {

  shoppingCart: CartDetail[] = [
    { productName: 'Hammer', quantity: 1 },
    { productName: 'Purple Shorts', quantity: 26 },
    { productName: 'Web Shooter', quantity: 2 }
  ];

  totalCartQuantity = mapArraySum(this.shoppingCart, item => item.quantity);
}

Wow, this is a much simpler approach. Furthermore, the dependency is completely decoupled from anything Angular-specific like @Injectable. Which implementation should you use? There are several considerations that should factor into this decision.

When to Consider Using ECMAScript 2015 Modules

The reason the ShoppingCartService is probably not a good candidate for straight ES2015 module dependency management is twofold. First, the UI of a shopping cart is generic enough where you may want to re-use the shopping cart UI components in multiple applications. These applications may employ different shopping cart logic. Second, the checkout process is prone to business changes and totaling a cart may change very much depending on promotions, shipping rates, or other business rules. You may find that calculation can no longer be done on the client and must involve a call to the server.

Potentially, it makes sense to employ both implementations where the ShoppingCartService exists as a loosely-coupled dependency yet its implementation leverages the generic mapArraySum function.

shopping-cart.service.ts

import { Injectable } from '@angular/core';
import { CartDetail } from './shopping-cart.model';
import { mapArraySum } from './mapArraySum';

@Injectable()
export class ShoppingCartService {
  getTotalQuantity(cartDetails: CartDetail[]): number {
    const total = mapArraySum(this.shoppingCart, item => item.quantity);
    return total;
  }
}

Before detailing what criteria indicates a potential candidate for ES2015 dependency management, remember that when in doubt the safer choice is to use Angular's dependency injection. In the end, it provides much greater flexibility if you ever need it.

These criteria potentially identify code suitable to use ES2015 dependency management:

  1. Pure functions with stateless logic (e.g. calculations, validations, mapping data structures)
  2. No external dependencies (e.g. HTTP requests)
  3. Generic functionality (e.g. language-level functionality, contract-based data mapping)
  4. Throw-away code for prototyping purposes

Given these criteria, and other than rough prototypes, what type of code specifically does this cover? This type of code can go by many names, but falls into the category of utility functions. This is code that helps you do things that you repeatedly do in any JavaScript application. It's the code you get sick of writing over and over. A simple example is a function that checks if an object is null or undefined.

export function isNullOrUndefined(value: any) {
    const isNullOrUndefined = value === null || value === undefined;
    return isNullOrUndefined;
}

This is a one-liner, but consider building on it:

export function isAnyNullOrUndefined(values: any[]) {
    // this would be more lines without support for .some()    
    const isAnyNullOrUndefined = values.some(value => isNullOrUndefined(value));
    return isAnyNullOrUndefined;
}

// another common example
export function isEmptyString(value: string) {
    const isEmptyString = !isNullOrUndefined(value) && value.length === 0;
    return isEmptyString;
}

What about a function that adds all the numbers in an array and rounds to a specific number of decimal places? This logic is prone to errors or inconsistencies in implementation. Do you round before or after you add? How do you guard against precision errors? These are all things a developer shouldn't have to keep revisiting while building an application. How do you perform a deep clone or a deep compare of two objects? These are all examples of common logic that developers use again and again.

Could you still put this logic in an Angular service and inject it into a component? Absolutely. The point is that you have another option that might prove more simple, elegant, and/or re-usable. Ultimately, choose what's best for your team and your project.

Use ES2015 Modules to Abstract Hard Dependencies

You may have been thinking during the last section, "Aren't there utility libraries to use for these types of utility functions?". There are and developers use them every day. The question is, should your application take a hard dependency on these libraries?

Based off the information thus far, this functionality can probably safely exist as an ES2015-based dependency. However, you can partially ease the coupling by abstracting the specific framework or library reference to within a library under your control. In this way, if you decide for examples that lodash's deep compare function is no longer required because of an emerging ECMAScript standard, you can easily replace it in one place without affecting the rest of the application.

Consider an isEqual module:

isEqual.ts

import * as _ from 'lodash.isequal';

export function isEqual(target: any, comparison: any) {
    const isEqual = _.isEqual(target, comparison);
    return isEqual;
}

app.component.ts

import { isEqual } from './app-utility/isEqual.ts';

@Component({
    selector: 'my-app',
    template: './app.component.html'
})
export class AppComponent {
    foo: any;

    onSomeEvent(newFoo: any) {
        if (isEqual(this.foo, newFoo)) {
            return;            
        }

        console.log('foo is new');
        this.foo = newFoo;
    }
}

So instead of repeatedly coupling your components to third party libraries, depend on your own utility library where you can replace or remove third-party utility libraries as necessary.

Conclusion

Again, this post is intended to help you think more deeply about the dependencies in your Angular application. There are many different approaches to handling these designs. What approaches do you use to manage dependencies in your applications?

Google I/O 2017 Talks for Angular Developers

Google I/O 2017 Talks for Angular Developers

In keeping with conference season, here is a list of videos for Angular developers from Google I/O 2017. While Google is arguably the most important company to the open web between Google Search and Chrome, they have other large platforms targeted at backend and native mobile developers. The breadth of Google's offerings can make it difficult to find the resources targeted at the front-end, Angular developer.

This is a collection of videos from this year's conference separated by category. While there are only a few Angular-specific videos (for more, look at the ng-conf 2017 list here), there are many sessions looking at the broader web platform, progressive web applications (PWA), and web components with Polymer. In addition to these core technologies, there are also videos listed for other technologies that are relevant or are becoming relevant for Angular developers like AMP and AR/VR.

Enjoy the below curated list of videos. To view all the videos from Google I/O, check out the playlist on YouTube.

Keynotes

General Web Platform

Progressive Web Applications

Web Components and Polymer

User Experience, Accessibility, and Design

Firebase

Artificial Intelligence and Machine Learning

Virtual Reality and Augmented Reality

That's the list. If you have a favorite, let everyone know in the comments.

Build 2017 Videos for Angular Developers

Build 2017 Videos for Angular Developers

After watching approximately six hours of keynote videos from Microsoft's Build Conference 2017, it's clear that no single company produces more software for developers than Microsoft. There are tools for virtually every platform. There are SDKs for Windows, Xbox, and Office. You can even use Visual Studio to develop an extension for Visual Studio.

With so many developer products, how do you determine which is relevant to you? That question is the inspiration for this post.

The following is a categorized list of videos from Build 2017 that are most relevant to an Angular web developer. The usual suspects are here including TypeScript, Visual Studio 2017, Visual Studio Code, Progressive Web Apps (PWA), ASP.NET, and Node.js. Going further are newer technologies such as Azure Serverless products, brand-new Cosmos DB, Mixed Reality, Artificial Intelligence offerings, and the debut of Fluent Design.

For the full list of all 450 videos, visit the event page on Channel9. Also if you find a favorite video absent from the list, please leave a comment.

Angular and Front-End

Tooling

Visual Studio Code

Visual Studio 2017

More Tooling

ASP.NET

Node.js

Azure – Serverless

Keynotes

Mixed Reality

Azure – Cosmos DB

Microsoft Graph

Fluent Design

Artificial Intelligence (AI)

Bot Framework

Cognitive Services

More AI

Favorite Talks from ng-conf 2017

ng-conf 2017 Favorite Talks

In early April, Angular developers from around the world attended ng-conf 2017. It's arguably the biggest Angular event of the year and it's always loaded with the latest Angular technologies and techniques. Having gone through much of this year's videos, here are some favorites with notes to help you decide if a video is relevant to you.

Thank you to everyone who makes this event great every year and for sharing the experience with those who couldn't be there in person. Enjoy the videos!

It's All About the Angular Baby and Angular Router Authentication and Authorization Real LIVE LIVE LIVE LIVE LIVE
Shai Reznik

These videos are for straight comedic value. Shai Reznik is the creator of the infamous ng-wat video from ng-conf two years ago. While It's All About the Angular Baby is pure entertainment. However, Shai manages to teach you a few things while making you laugh in his authentication and authorization talk.

Everything is a plugin! Mastering webpack from the inside out
Sean Larkin

This is a must-watch if only for the fact that Sean Larkin walks you through how to debug a webpack build. The talk is divided into 3 parts. First, Sean explains the different pieces of a webpack build with a hand-drawn illustration. If you're looking to save time going through this two-hour video, consider skipping the second part which is answering questions and handing out shirts. A highlight during this part is that WebAssembly is apparently an important technology on webpack's roadmap.

Finally, the talk continues with a workshop on creating a webpack plugin. Grab your laptop. Sean walks through the process step-by-step, answering questions along the way (including how to get some Mac commands to work on Windows). A personal favorite, he demonstrates the important skill of debugging webpack. Visit this timestamp to skip ahead to the walkthrough. This talk is highly recommended.

I am one with Angular, Angular is one with me
John Papa

This is a relatively short, 20-minute talk on tooling. John walks through his favorite features of the Angular CLI, Visual Studio Code, and Angular v4 TypeScript Snippets. He also touches on the new language service plugin for Visual Studio Code which provides IntelliSense for template bindings.

The Angular CLI has so many features and John demonstrates the dry-run flag, lazy loading routes, and automatically providing newly-generated services. You also see how insanely productive he is using the Angular v4 TypeScript Snippets plug-in for Visual Studio Code. Watch this talk to level up your Angular-Fu!

Using the Angular Template Language Service
Chuck Jazdzewski

This is a great overview on the status of the Angular Language Service. This service works with TypeScript to provide IntelliSense and easy refactoring capabilities in your Angular markup. It promises to provide compile-time checking for template errors that are currently only detectable at runtime. Chuck covers everything, discussing the tooling's architecture, roadmap, and editor support.

Thoughtful Component Design
Jeremy Elbourn and Miles Malerba

This talk is presented by two members of the Angular Material team where they discuss their findings from building a component library. There are many useful topics discussed. How do you maintain native DOM behavior for elements like INPUT while providing enhanced functionality with Angular? How and when should you 'touch the DOM'? For anyone looking to improve their component API design, this talk delivers.

Packaging Angular
Jason Aden

This talk is critical to anyone using Angular across teams in a large organization. Jason discusses the best practices for sharing components in an npm package. What should you include? He goes over including AOT support, Type Definitions, metadata files and shows how to create and optimize these artifacts. He provides straight-forward advice such as using one NgModule per Component and discusses build optimizations using the Closure Compiler.

From Inactive to Reactive with ngrx
Brandon Roberts & Mike Ryan

This is an introduction to the ngrx library for state management. The talk covers the basics of the ngrx libraries as well as the concepts it leverages from redux. This is recommended for anyone new to ngrx or redux.

Keynote Day 3
Brad Green and Rob Wormald

This is really two talks in one. Brad gives a peek behind the curtain at Google's process for adopting new technologies and how that influences their decisions with Angular. While this doesn't necessarily affect most developers, it's an interesting story nonetheless.

In the second part of the talk, Rob Wormald discusses the importance of new features including platform-server (Angular Universal) and Angular Mobile which promise to provide increased performance and SEO capabilities to Angular applications.

Angular Pre-Rendering for SEO, Speed, and Happy Users
Jeff Cross

This is about platform-server (Angular Universal). This framework has now moved under development by the Angular team. It provides server-side rendering for Angular applications. This provides several benefits including improved performance, better scrape-ability for social scrapers, and better SEO for crawlers.

Jeff goes into many of the aspects of implementing these benefits and highlights some of the tradeoffs and considerations at play. If these benefits matter to your site, this is a very well done presentation.

Automatic Progressive Web Apps using the Angular Mobile Toolkit
Maxim Slanikov

This talk is all about the Angular Mobile framework which aims to provide out-of-the-box progressive web app (PWA) features for Angular developers. Many consider PWAs to be (at least part of) the future of delivering applications to devices. It appears that this framework is still in the preview stages and Maxim cautions about existing documentation. If PWAs are important to you, find out how to get started with this talk.

The Angular Compiler 4.0
Tobias Bosch

This is an inside look at the changes made to the compiler in Angular 4. Tobias explains how the Angular compiler works and what it produces. He further explains what was changed to improve performance as well as the test data proving the results.

Docker: What Every Angular Developer Should Know About It!
Dan Wahlin

As the title suggests, this talk is about Docker. Dan takes an application created with the Angular CLI and hosts it on Nginx inside of a Docker container. He goes through the main benefits and features of Docker relevant to web developers and demonstrates their implementation. Dan is a great speaker and if you are new to Docker, this is a great overview.

The Day I Met Steve
Alyssa Nicoll

This is a short soft-skills talk but one that's important. Alyssa looks at how and why developers get discouraged at work. She provides some useful tips on how to avoid this path ourselves and how to create an environment where everyone feels their contributions matter.

Whether you work with WordPress sites or not, Roy explains how and why you might want to start. WordPress claims to run 27% of the internet and there is a large community of support for this system. How can you leverage this support for your Angular applications? The answer is to use the WordPress REST API and this talk gives an overview of how it works. It also has a lot of cat pictures if you're into that kind of thing.

In Summary

There are over 60 videos posted from the conference and this is only a sampling. To watch more, check out the playlists on YouTube. If you have a favorite, please mention it in the comments below.

ASP.NET Core JavaScript Services with Webpack HMR

ASP.NET Core JavaScript Services with Webpack HMR Hero

Derived from photo by Alasdair / flickr.com, CC BY

This tutorial covers two aspects of the ASP.NET Core JavaScript Services library. First, MapSpaFallbackRoute, is a utility to help redirect client-side routes to the browser. Second is a utility for integrating webpack dev middleware as ASP.NET Core middleware. This provides webpack's hot module replacement (HMR) functionality integrated with the ASP.NET Core request pipeline. When this is enabled, the code in the browser automatically replaces the updated ES2015 module without a full application refresh. This is an incredibly productive development setup.

The tutorial uses Visual Studio Code as the editor. If you would like to go directly to the completed example, the code is on GitHub.

Initial Setup

  1. Follow the steps in this post to create an 'empty' Angular, ASP.NET Core project using the Angular and dotnet command line interfaces (CLI). The rest of the tutorial builds off this base project.
  2. Next, add the code for multiple components to the project's src/app directory. Upon completion, the files should be in this structure with the following contents:

    ├── src
    |   ├── app
    |   |   └── app.component.ts
    |   |   ├── app.module.ts
    |   |   ├── base.component.html
    |   |   ├── main.component.ts
    |   |   └── other.component.ts
    

    app.component.ts

    import { Component } from '@angular/core';
    
    // exported to use with webpack HMR
    export const rootElementTagName = 'app-root';
    
    @Component({
    selector: rootElementTagName,
    template: `
      <nav>
        <a routerLink="/main">main</a> |
        <a routerLink="/other">other</a>
      </nav>
      <router-outlet></router-outlet>
    `
    })
    export class AppComponent { }
    

    base.component.html

    <h1>
    {{title}}
    </h1>
    

    main.component.ts

    import { Component } from '@angular/core';
    
    @Component({
    selector: 'app-main',
    templateUrl: './base.component.html'
    })
    export class MainComponent {
    title = 'this is the main component';
    }
    

    other.component.ts

    import { Component } from '@angular/core';
    
    @Component({
    selector: 'app-other',
    templateUrl: './base.component.html'
    })
    export class OtherComponent {
    title = 'this is the other component';
    }
    
  3. Finally, configure components in the NgModule app.module.ts.

    app.module.ts

    import { BrowserModule } from '@angular/platform-browser';
    import { NgModule } from '@angular/core';
    import { FormsModule } from '@angular/forms';
    import { HttpModule } from '@angular/http';
    import { RouterModule, Routes } from '@angular/router';
    
    import { AppComponent, rootElementTagName } from './app.component';
    import { MainComponent } from './main.component';
    import { OtherComponent } from './other.component';
    
    const routes: Routes = [
    { path: '', redirectTo: '/main', pathMatch: 'full' },
    { path: 'main',  component: MainComponent },
    { path: 'other', component: OtherComponent },
    ];
    
    @NgModule({
    declarations: [
      AppComponent,
      MainComponent,
      OtherComponent
    ],
    imports: [
      BrowserModule,
      FormsModule,
      HttpModule,
      RouterModule.forRoot(routes)
    ],
    providers: [],
    bootstrap: [AppComponent]
    })
    export class AppModule { }
    
    export { rootElementTagName } from './app.component';
    

    Now run the application in Visual Studio Code using F5. The client-side routes are configured and you can switch between the main and other views.

Configure Server-Side Routing with MapSpaFallbackRoute

The ASP.NET Core JavaScript Services library includes a utility to configure single page application (SPA) routing. This enables the server to handle any requests intended for the Angular router by returning the Angular application to the browser. Once the browser loads the Angular application, Angular takes over the URL routing. For more information on how Angular and ASP.NET Core routes integrate, see this post.

These steps configure server-side routing.

  1. Within the project directory, use the command dotnet add package Microsoft.AspNetCore.SpaServices to add the ASP.NET Core JavaScript Services library to the project. Restore the new package when Visual Studio Code displays the prompt or by using the command dotnet restore.

  2. In the Startup.cs file add the ASP.NET MVC service as well as the MapSpaFallbackRoute:

    Startup.cs

    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.AspNetCore.SpaServices.Webpack;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.Logging;
    
    namespace my_directory
    {
    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 https://go.microsoft.com/fwlink/?LinkID=398940
      public void ConfigureServices(IServiceCollection services)
      {
        services.AddMvc();
      }
    
      // 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.UseDefaultFiles();
        app.UseStaticFiles();     
    
        app.UseMvc(routes => {
          routes.MapSpaFallbackRoute(
            name: "spa-fallback",
            defaults: new { controller = "Home", action = "Index" });
        });
      }
    }
    }
    

    Note: Ensure that the namespace my-directory is replaced with the namespace of your application.

  3. The MapSpaFallbackRoute points to a HomeController. Create a Controllers directory and add this controller as a pass-through to simply return the Angular application for routes that should be addressed on the client.

    HomeController.cs

    using Microsoft.AspNetCore.Mvc;
    
    public class HomeController : ControllerBase
    {
      public IActionResult Index()
      {
          var fileName = "index.html";
          var contentType = "text/html";
    
          return File(fileName, contentType);
      }
    }
    

Run the application with F5. Go directly to the URL http://localhost:5000/other in the browser's address bar (not by linking from within the application) and see that the Angular application successfully loads the route.

Configure Hot Module Replacement

One of the more compelling features of webpack is its ability to apply code updates in the browser while the application is running so you can quickly see the resulting changes. This is webpack's Hot Module Replacement (HMR) feature and the JavaScript Services library includes the ability to integrate with this functionality using ASP.NET Core middleware.

  1. Type ng eject in the terminal to have Angular CLI switch the configuration to a webpack-based configuration. At this point any configuration changes that you want to make to the build must be done through the webpack configuration. The Angular CLI configuration no longer applies.

  2. Run npm install aspnet-webpack webpack-hot-middleware -D to download required Node.js packages. Also, run npm install to ensure all the new webpack package dependencies are downloaded.

  3. Configure the webpack middleware in the Startup.cs file. Add the webpack dev middleware configuration within the env.IsDevelopment() conditaion. By default, Visual Studio Code configures ASP.NET Core to run in Development mode so this condition evaluates to true.

    Startup.cs

    // ...
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
    // ...
    if (env.IsDevelopment())
    {
      app.UseDeveloperExceptionPage();
      app.UseWebpackDevMiddleware(new WebpackDevMiddlewareOptions {
        HotModuleReplacement = true
      });
    }
    
    app.UseDefaultFiles();
    
    // ...
    }
    
  4. When running the project with webpack HMR, you do not need to build with webpack as part of the .csproj build. Update this configuration to avoid the extra processing at compile time. By default, the build runs with a 'Debug' configuration which will not trigger the webpack build.

    my-directory.csproj

    <Target Name="AngularBuild" AfterTargets="Build">
    <Exec Condition="'$(Configuration)' == 'Release'" Command="npm run build" />
    </Target>
    

    Note: Attentive readers may notice that the tutorial uses ASP.NET Core configuration for enabling the webpack dev middleware and alternatively a build configuration constant for enabling the non-HMR build. This tutorial focuses on improving the developer experience with webpack HMR. There are many options for synchronizing these configurations to be explored in future posts.

  5. Set "publicPath" to "/" in the webpack.config.js file under the "output" section.

    "output": {
    "path": path.join(process.cwd(), "wwwroot"),
    "filename": "[name].bundle.js",
    "publicPath": "/",
    "chunkFilename": "[id].chunk.js"
    },
    
  6. Finally, you must handle the HMR changes in the browser to refresh the Angular application with updated modules. Add a TypeScript file to the src directory named handleHotModule.ts and use it to handle the HMR changes during the Angular bootstrap process in main.ts.

    handleHotModule.ts

    import { Type, PlatformRef } from '@angular/core';
    
    interface HotModule extends NodeModule {
    hot?: HotModuleHandler;
    }
    
    interface HotModuleHandler {
    accept: () => void;
    dispose: (callback: () => void) => void;
    }
    
    export function handleHotModule(
    bootstrapModule: HotModule,
    rootElemTagName: string,
    platform: PlatformRef,
    bootFunction: (isModuleHot: boolean) => void
    )  : void {
    const isModuleHot = !!bootstrapModule.hot; 
    
    if (isModuleHot) {
      bootstrapModule.hot.accept();
      bootstrapModule.hot.dispose(() => {
        const oldRootElem = document.querySelector(rootElemTagName);
        const newRootElem = document.createElement(rootElemTagName);
        oldRootElem.parentNode.insertBefore(newRootElem, oldRootElem);
        platform.destroy();
      });
    }
    
    if (document.readyState === 'complete') {
      bootFunction(isModuleHot);
    } else {
      document.addEventListener('DOMContentLoaded', () => {
        bootFunction(isModuleHot);
      });
    }
    }
    

    main.ts

    import { enableProdMode } from '@angular/core';
    import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
    
    import { AppModule, rootElementTagName } from './app/app.module';
    import { environment } from './environments/environment';
    import { handleHotModule } from './handleHotModule';
    
    const platform = platformBrowserDynamic();
    
    handleHotModule(module, rootElementTagName, platform, isModuleHot => {
    if (environment.production && !isModuleHot) {
      enableProdMode();
    }
    
    platform.bootstrapModule(AppModule);
    });
    

    Now run the application. After the application loads, make a change to one of the components and save the file. Upon saving, you see the update appear in the browser almost immediately after you press save in the editor.

Your New Developer Experience

Welcome to your new developer experience with ASP.NET Core and Angular powered by webpack and ASP.NET Core JavaScript Services. The ASP.NET Core JavaScript Services library has so much more including server-side pre-rendering with Angular Universal and lower level utilities to interface with Node.js code.

Take some time to look at the respository on GitHub. There are additional details included there for your reference.

Give this setup a try and drop a comment about your experience. What other build configurations and developer features do you want to see featured on the blog?

Get Going with the Angular and ASP.NET CLIs

Angular and ASP.NET CLIs Header

When learning Angular and ASP.NET Core, it's oftentimes helpful to start with an empty project. However, there are some integration steps required to have Angular and ASP.NET Core work together.

This tutorial shows how to create an Angular, ASP.NET Core project using the command line interfaces (CLI) for both Angular and .NET Core. It demonstrates how to host and debug an ASP.NET Core project in Visual Studio Code.

Prerequisites

The following must be installed to complete this tutorial:

Note: The commands in this article work on a Windows machine with PowerShell. Other platforms may require modifications.

Configure Angular

  1. Install Angular CLI globally to make the commands available in any directory

    npm install -g @angular/cli
    
  2. Use the newly installed Angular CLI to scaffold a new project. This command creates a new directory to house your application. It may take a couple minutes to complete because the utility installs the npm packages for Angular, the build, and testing.

    ng new my-directory
    
  3. Navigate into the repository and verify the application by running it with the Angular CLI. Use the --open argument to open the application in the default browser.

    cd my-directory
    ng serve --open
    

    The Angular CLI runs the application on a Node.js web server and you will see the stub page.

    Angular CLI Stub Page

  4. Terminate the running web server with the key combination Ctrl + C to continue in the command window.

Configure ASP.NET Core

  1. In the repository, use the .NET Core CLI to scaffold an empty ASP.NET Core project.

    dotnet new web
    

    Note: The dotnet new command scaffolds the .NET project within the current working directory whereas the Angular CLI command ng new creates a new directory to contain the generated Angular code.

  2. Install the ASP.NET static file support middleware.

    dotnet add package Microsoft.AspNetCore.StaticFiles
    
  3. Open the repository in Visual Studio Code

    code .
    
  4. Visual Studio Code prompts you to configure the application and to restore .NET packages. Press Yes and Restore respectively. The editor generates a .vscode folder containing configuration files and downloads the .NET Core dependencies.

    .NET Core Configuration Prompt

    Tip: If the prompt doesn't appear initially, open a C# file in the editor.

  5. Configure the Angular CLI to output the Angular build to the wwwroot folder. Open the .angular-cli.json configuration file and change "outDir": "dist" to "outDir": "wwwroot".

    {
    // ...
    "apps": [
     {
        "root": "src",
        "outDir": "wwwroot",
        // ...
    }
    }
    
  6. Configure static file support in the Startup.cs file. The Configure method should have the following code.

    public void Configure(IApplicationBuilder app,
      IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
      loggerFactory.AddConsole();
    
      if (env.IsDevelopment())
      {
          app.UseDeveloperExceptionPage();
      }
    
      app.UseDefaultFiles();
      app.UseStaticFiles();
    }
    
  7. Add a build step to the .csproj file to build the Angular application with the Angular CLI.

    <Target Name="AngularBuild" AfterTargets="Build">
      <Exec Command="npm run build" />
    </Target>
    
  8. Press the F5 key to run the ASP.NET application with Visual Studio Code's debugger. The Angular application is now hosted from ASP.NET Core instead of Node.js. Notice how ASP.NET Core uses port 5000 by default as opposed to 4200 with the Angular CLI.

    Angular CLI Stub Page on ASP.NET Core

    Completed Startup.cs Code:

    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 my_directory
    {
      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  https://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.UseDefaultFiles();
            app.UseStaticFiles();
        }
      }
    }
    

    Completed my-directory.csproj Code:

    <Project Sdk="Microsoft.NET.Sdk.Web">
    <PropertyGroup>
      <TargetFramework>netcoreapp1.1</TargetFramework>
    </PropertyGroup>
    
    <ItemGroup>
      <Folder Include="wwwroot\" />
    </ItemGroup>
    
    <ItemGroup>
      <PackageReference Include="Microsoft.AspNetCore" Version="1.1.1" />
      <PackageReference Include="Microsoft.AspNetCore.StaticFiles"  Version="1.1.1" />
    </ItemGroup>
    
    <Target Name="AngularBuild" AfterTargets="Build">
      <Exec Command="npm run build" />
    </Target>
    </Project>
    

Conclusion

The tooling has finally come together for both Angular and ASP.NET so that anyone can easily create an application using the command line.

Use the steps here to build the foundation and then move to integrate other features like routing and authentication. In fact, learn to integrate routing right here.

Have you been using the CLI for Angular or ASP.NET Core? What do you like or dislike about them? Please leave a note in the comments.