Thursday, June 21, 2018

A10–Building App using Angular and ASP.NET Core 2.1–Services, Events and Cross Component Communication

This post is a part of a series of posts that I am writing as I am building an app using Angular and ASP.NET Core 2.1. Links to previous posts –> A1, A2, A3, A4, A5, A6, A7, A8, A9 Github Repo

Today, I was able to accomplish few things,

1. Added Shopping service that adds product and updates shopping cart

2. Established cross component communication via Shopping Service (Home Component –> Add To Cart –> Updates Shopping Cart

3. Created API for adding and getting products from ShoppingCart Controller. I am returning hard coded products and hence you will always see two shown at the top right.

Right now I didn’t wanted to create any database backend. I want to just make sure client server interaction is in sync. Once I like how everything is structured then I will invest time into adding database layer. Below is code for Shopping Service.

import { Injectable, Inject } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Product } from '../product/product';
import { catchError, map, tap,last } from 'rxjs/operators';
import 'rxjs/add/observable/throw';
import { of } from 'rxjs/observable/of';
import { Observable } from 'rxjs/Observable';
const httpOptions = {
  headers: new HttpHeaders({
    'Content-Type': 'application/json'
  })
};
@Injectable()
export class ShoppingService {

  private _baseUrl: string;
  private cartQuantitySource = new BehaviorSubject(0);
  currentCartQuantity = this.cartQuantitySource.asObservable();

  private _addProductToShoppingCart: string = "api/ShoppingCart/Add/";
  private _getProductsFromShoppingCart: string = "api/ShoppingCart/Products";
  constructor(private _http: HttpClient, @Inject('BASE_URL') baseUrl: string) {
    this._baseUrl = baseUrl;
    this.updateCartQuantity(); 
  }

  updateCartQuantity() {
    this._http.get<Product[]>(this._baseUrl + this._getProductsFromShoppingCart).subscribe(products => {
      this.log(`getting products from shopping cart`);
      this.cartQuantitySource.next(products.length);
    });
  }

  addProductToCart(product: Product) {
    this._http.post(this._baseUrl + this._addProductToShoppingCart + product.id, product, httpOptions).subscribe(x => {
      this.log(`added Product To Shopping Cart`);
      this.updateCartQuantity();
    });    
  }

  private handleError<T>(operation = 'operation', result?: T) {
    return (error: any): Observable<T> => {
      console.log(error); //log to console instead       
      this.log(`${operation} failed: ${error.message}`);
      return Observable.throw(error || 'Server error');
    };
  }
  private log(message: string) {
    console.log("Shopping Service " + message);
  }
}

One of the things, I am not liking is how api urls are hard coded as strings. This is something I want to improve upon. I will put them inside an injectable service which has all the urls.

Next thing I want to learn is authentication and authorization with ASP.NET Core.

Wednesday, June 20, 2018

A9–Building App using Angular and ASP.NET Core 2.1–Font-awesome, Pagination and Layout

This post is a part of a series of posts that I am writing as I am building an app using Angular and ASP.NET Core 2.1. Links to previous posts –> A1, A2, A3, A4, A5, A6, A7, A8, Github Repo

Today, I got carried away with home page layout and wasn’t able to fix communication between components. I spent trying to add pagination using some blogpost but then I discovered ngx-pagination. Below are things I was able to do.

1. Added pagination using ngx-pagination npm package it was pretty straight forward

2. Added font-awesome npm package so I could add shopping cart icon.

3. Added pagination to home page and products page

4. Added shopping-cart-widget component for displaying cart information

image

Next, I want to fix communication between components, ie. when you click on add to cart button it should add items to cart and call server side api method.

See ya next time.

Tuesday, June 19, 2018

A8–Building App using Angular and ASP.NET Core 2.1–SASS and Responsive Layout

This post is a part of a series of posts that I am writing as I am building an app using Angular and ASP.NET Core 2.1. Links to previous posts –> A1, A2, A3, A4, A5, A6, A7, Github Repo

Today, I could accomplish very little.

1. Fixed cards layout for home page

I like to put borders and see how where the boxes are.

image

As we change screen size, we can see responsive design at work.

image

Another one

image

image

Alright I messed this one up, I want to make this look different. However, I am running out of time for today.

image

2. From the screenshots above, menu has been fixed and is also responsive.

3. Using SASS syntax was something new—you don’t have to put {} and ; and indentation like python. So I will have to get used to this syntax.

Next, I will have to continue fixing home page styling and then I will follow up on adding more product information. I am excited to work on server side logic.

See ya next time.

Monday, June 18, 2018

A7–Building App using Angular and ASP.NET Core 2.1–Bootstrap 4, SASS, Cleanup

This post is a part of a series of posts that I am writing as I am building an app using Angular and ASP.NET Core 2.1. Links to previous posts –> A1, A2, A3, A4, A5, A6, A7, Github Repo

On training side, I finished watching Beginner Path for Angular on Pluralsight. I learnt some nice things about Angular CLI. I didn’t knew that Angular app can be created using SASS, CSS or LESS as default way of creating style files. Dry run option is awesome. I always liked how PowerShell had –WhatIf flag and every CLI should have these types of commands.

Let’s cover all the things I was able to accomplish today.

1. Refactored app.module.ts file to make it leaner. I moved all product related components, routes and services into product module. In the image below, on the left everything in red was moved into product module.

image

2. Set the default style extension to be SASS and renamed all .css files to .sass. Right now I didn’t not create any styles into any sass file. Ahem, have to learn first right. Actually, I heard it is not very different than .less so will see how sass is. I had to delete navmenu component styles that were created by default template.

image

3. While I have worked with Bootstrap 3 a lot, I wanted to learn Bootstrap 4 in this project so I updated to Bootstrap 4. When you install Bootstrap 4 in an angular project, npm doesn’t install jquery, popper.js libraries so, I had to install those. I had to fix styling for home page and navigation to use Bootstrap 4.

image

4. Other visual and layout changes includes moving nav menu to top, moving home page content to about page, adding products to home page for people to view products on sale.

image

You can see home page with product cards. The UI is all messed up right now. There are many changes need to be made to how cards are displayed. The bottom card is completely hideous—taking up whole page.

image

5. Bug fix. In product.service.ts there was bug found in the handleError function which was returning default type. It should have thrown error. This prevented server side validation error from being displayed to our user.

image

So that’s all for today. The app is completely garbage right now but I am making progress. My next goals are as follows:

1. Make home page UI responsive, add style for product cards, make navigation menu responsive and add more data to display cards appropriately.

2. Add product description and other product related meta data, display that data accordingly on home page, add more complex data validation—using dates and dropdown.

See ya next time.

Friday, June 15, 2018

A6–Building App using Angular and ASP.NET Core 2.1– Cleanup, Host on Azure, CI and CD pipeline

This post is a part of a series of posts that I am writing as I am building an app using Angular and ASP.NET Core 2.1. Links to previous posts –> A1, A2, A3, A4, A5 Github Repo

Here what I was able to accomplish today.

1. Cleanup default files created by Project template

2. Write readme document

3. Create CI and CD Pipeline using VSTS

4. Host on Azure App Service using Free Tier (link).

image

Hosted web site can be found here.

image

Thursday, June 14, 2018

A5–Building App using Angular and ASP.NET Core 2.1 – Services Dependency Injection

This post is a part of a series of posts that I am writing as I am building an app using Angular and ASP.NET Core 2.1. Links to previous posts –> A1, A2, A3, A4, Github Repo

Today my goal is to extract httpclient into a product service. And finish delete page.

Below is the code for extracted ProductService.

import { Injectable, Inject } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { Product } from './product';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { catchError, map, tap } from 'rxjs/operators';
import { of } from 'rxjs/observable/of';
const httpOptions = {
  headers: new HttpHeaders({
    'Content-Type': 'application/json'
  })
};

@Injectable()

export class ProductService {

  
  private _baseUrl: string;
  private _productListUrl: string = "api/Product/List";
  private _productInsertUrl: string = "api/Product/Insert";
  private _productEditUrl: string = "api/Product/Edit";
  private _productFindUrl: string = "api/Product/Find/";
  private _productDeleteUrl: string = "api/Product/Delete/";
  constructor(private _http: HttpClient, @Inject('BASE_URL') baseUrl: string) {
    this._baseUrl = baseUrl;
  }

  getProduct(id: number): Observable<Product> {
    return this._http.get<Product>(this._baseUrl + this._productFindUrl + id)
      .pipe(
        tap(product => this.log(`fetched product`)),
        catchError(this.handleError<Product>('getProduct'))
      );
  }

  getProducts(): Observable<Product[]> {
    return this._http.get<Product[]>(this._baseUrl + this._productListUrl)
      .pipe(
        tap(products => this.log(`fetched products`)),
        catchError(this.handleError('getProducts', []))
      );
  }

  insertProduct(product: Product): Observable<Product> {
    return this._http.post<Product>(this._baseUrl + this._productInsertUrl, product, httpOptions)
      .pipe(
        tap(products => this.log(`fetched products`)),
        catchError(this.handleError<Product>('insertProduct'))
      );
  }

  editProduct(product: Product): Observable<Product> {
    return this._http.post<Product>(this._baseUrl + this._productEditUrl, product, httpOptions)
      .pipe(
        tap(products => this.log(`fetched products`)),
        catchError(this.handleError<Product>('editProduct'))
      );
  }

  deleteProduct(product: Product): Observable<any> {
    return this._http.post<Product>(this._baseUrl + this._productDeleteUrl + product.id, product, httpOptions)
      .pipe(
        tap(products => this.log(`fetched products`)),
        catchError(this.handleError<Product>('deleteProduct'))
      );
  }

  private handleError<T>(operation = 'operation', result?: T) {
    return (error: any): Observable<T> => {

      console.log(error); // log to console instead      
      this.log(`${operation} failed: ${error.message}`);      
      return of(result as T);
    };
  }
   
  private log(message: string) {
    console.log("Product Service" + message);
  }
}

One of the things, I realized is that dotnet watch run sometimes will get stuck processing requests and it will feel like things have hanged. So I press Ctrl+C and dotnet watch will start processing things again. I have also hooked up Delete button with web api endpoint. Updated and working code is on Github Repo.

Next goal is to clean up default pages created by ASP.NET Core SPA template and host it on Azure website.

Wednesday, June 13, 2018

A4–Building App using Angular and ASP.NET Core 2.1 – Posting Form Values, Server-Side Validation, Displaying Error Messages

This post is a part of a series of posts that I am writing as I am building an app using Angular and ASP.NET Core 2.1. Links to previous posts –> A1, A2, A3, Github Repo

Today, my goal is hook up submit button for Insert, Edit and Delete Pages with HttpClient and post form values to ASP.NET Core Web API backend.

Below is code for product-insert.component.ts file, the code for product-edit.component.ts is same. Initially I am using HttpClient directly inside component.

import { Component, OnInit, Inject } from '@angular/core';
import { Product, IProduct } from '../product';
import { HttpClient, HttpHeaders } from '@angular/common/http';

const httpOptions = {
  headers: new HttpHeaders({
    'Content-Type': 'application/json',
    'Authorization': 'my-auth-token'
  })
};


@Component({
  selector: 'app-product-insert',
  templateUrl: './product-insert.component.html',
  styleUrls: ['./product-insert.component.css']
})

export class ProductInsertComponent implements OnInit {

  public product: IProduct;
  private _baseUrl: string;
  constructor(private _http: HttpClient, @Inject('BASE_URL') baseUrl: string) {
    this.product = new Product("", 0);
    this._baseUrl = baseUrl;
  }


  onProductSave(product: IProduct) {
    console.log(JSON.stringify(product));
    this._http.post<Product>(this._baseUrl + 'api/Product/Insert', product, httpOptions)
      .subscribe(result => {
        console.log(result);
      }, error => console.log(error));
    
  }
  ngOnInit() {

  }

}

I tested that when I clicked Save button, http post is getting called and same object being returned. In the image below, you can see that first json object is from component and other one is returned from API call.

image

I want to add some server side validation. Let’s say that price of product should be greater than 100. If price is less than 100 then throw BadRequest from server and display to user that error.

  [HttpPost("[action]")]
        public ActionResult<Product> Insert([FromBody] Product product)
        {
            _validateProduct(product);
            if (ModelState.IsValid)
            {
                //TODO: Save Product to database.
                return product;
            }
            return BadRequest(ModelState);
        }

        private void _validateProduct(Product product)
        {
            if (product.Price < 100)
            {
                ModelState.AddModelError(nameof(Product.Price), $"Product price cannot be less than 100, you entered {product.Price}");
            }
        }

In the code above, if the product price is less than 100, I am adding model error for key Price and message. This message we will have to show it to the user.

import { Component, OnInit, Inject } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { ActivatedRoute } from '@angular/router';
import { Product, IProduct } from '../product';

const httpOptions = {
  headers: new HttpHeaders({
    'Content-Type': 'application/json',
    'Authorization': 'my-auth-token'
  })
};


@Component({
  selector: 'app-product-edit',
  templateUrl: './product-edit.component.html',
  styleUrls: ['./product-edit.component.css']
})
export class ProductEditComponent implements OnInit {

  public errors: string[];
  public product: Product;
  id: number;
  private _baseUrl: string;
  constructor(private _http: HttpClient, private _activeRoute: ActivatedRoute, @Inject('BASE_URL') baseUrl: string) {
    this._baseUrl = baseUrl;
    this.id = this._activeRoute.snapshot.params['id'];
    this._http.get<Product>(baseUrl + 'api/Product/Find/' + this.id).subscribe(result => {
      this.product = result;
    }, error => console.log(error));


  }

  onProductSave(product: IProduct) {
    console.log(JSON.stringify(product));
    this._http.post<Product>(this._baseUrl + 'api/Product/Edit', product, httpOptions)
      .subscribe(result => {
        console.log(result);
      }, error => {
        console.log(error.error);
        if (error.status === 400) {
          let allErrors = error.error;
          console.log(allErrors);
          for (var fieldName in allErrors) {
            if (allErrors.hasOwnProperty(fieldName)) {
              this.errors.push(allErrors[fieldName]);
            }
          }
        }
      });
  }

  ngOnInit() {
    this.errors = [];
  }

}

I found this post by Carl and I am following his post to show error messages returned. Thank you Carl.

<br />
  <div class="alert alert-danger" role="alert" *ngIf="errors.length > 0">
    <ul>
      <li *ngFor="let error of errors">
        {{ error }}
      </li>
    </ul>
  </div>

This is displayed as shown in the image below.

image

I am displaying server side error message like below and marking the control as invalid as shown below.

import { Component, OnInit, Inject } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { ActivatedRoute } from '@angular/router';
import { Product, IProduct } from '../product';
import { FormControl, AbstractControl } from '@angular/forms';

const httpOptions = {
  headers: new HttpHeaders({
    'Content-Type': 'application/json',
    'Authorization': 'my-auth-token'
  })
};


@Component({
  selector: 'app-product-edit',
  templateUrl: './product-edit.component.html',
  styleUrls: ['./product-edit.component.css']
})
export class ProductEditComponent implements OnInit {

  public errors: string[];
  public product: Product;
  id: number;
  private _baseUrl: string;
  constructor(private _http: HttpClient, private _activeRoute: ActivatedRoute, @Inject('BASE_URL') baseUrl: string) {
    this._baseUrl = baseUrl;
    this.id = this._activeRoute.snapshot.params['id'];
    this._http.get<Product>(baseUrl + 'api/Product/Find/' + this.id).subscribe(result => {
      this.product = result;
    }, error => console.log(error));


  }

  onProductSave(productForm: any) {
    console.log((productForm));
    productForm.controls;
    let product = productForm.value;
    
    this._http.post<Product>(this._baseUrl + 'api/Product/Edit', product, httpOptions)
      .subscribe(result => {
        console.log(result);
      }, error => {
        console.log(error);
        console.log(error.error);
        if (error.status === 400) {
          let allErrors = error.error;
          for (var fieldName in allErrors) {
            if (allErrors.hasOwnProperty(fieldName)) {
              if (productForm.controls[fieldName]) {
                productForm.controls[fieldName].markAsTouched();
                productForm.controls[fieldName].setErrors({ invalid: true });
                this.errors.push(allErrors[fieldName]);
              } 
            }
          }
        }
      });
  }

  ngOnInit() {
    this.errors = [];
  }

}

This way the field is marked as invalid. I would like to show message below the field but it is taking longer for me to figure out today.

image

So that’s it folks for today, you can find the code on Github.

Next goal is to extract httpclient into a product service. And finish delete page.

Tuesday, June 12, 2018

A3–Building App using Angular and ASP.NET Core 2.1 – Form Validation

This post is a part of a series of posts that I am writing as I am building an app using Angular and ASP.NET Core 2.1. Links to previous posts –> A1, A2, Github Repo

Today, my goal was adding form validation to form controls. I added validation to Insert and Edit pages for Product. Validation on both the pages is very similar.

Add Product Validation

image

Same page but validation changes if you delete price and keep it null.

image

I learnt couple of things today regarding validation and forms.

1. There are many things to remember in hooking up things with form. For example, creating multiple validation is not that straight forward.

2. Out of the box there are couple of validators but real world scenarios almost always require you to have custom validation.

3. I wish there was an alternative to template variable. I do not like creating these variable on input fields. From an api standpoint it would have been nicer if everything was part of ngModel.

These are my naïve observations and stupid opinions based upon my limited knowledge regarding Angular internals.

Regarding my app, I am realizing that there is more code common between add and edit component. Perhaps I could utilize some shared component here. I am not too concerned with this right now. To get good grasp at validation, I am going to add more fields later.

Next goal is to be able to submit edit, insert, delete product using ASP.NET Web API as backend. Until then have a good night. And code is on GitHub.

Monday, June 11, 2018

A2–Building App using Angular and ASP.NET Core 2.1 – GitHub & Forms

This post is a part of a series of posts that I am writing as I am building an app using Angular and ASP.NET Core 2.1. The first post can be found here.

My first goal is to put this code on GitHub so people can follow progress and goof ups. Here is the link. The repo is called A100. Why A100 name? Because I couldn’t come up with a better name. There is no logic. Everything can be changed at any time in software so I just picked something and moved on.

You can clone it into a folder and if you have latest .NET Core SDK 2.1 installed you will be able to run the project as shown below.

PS M:\github\A100\src\A100> dotnet watch run

dotnet watch run is the best thing about building .NET web apps. You can make changes to file and see your website updated. No need to keep refreshing.

There is just one issue with dotnet watch when working with Angular and ASP.NET Core. And that is multiple urls. In the image below, there are three ports listening 5001 (https), 5000 and some random port generated by ng 55267.

image

You can use any url to test your application.

Next I am creating different pages edit, insert, details for viewing product information.

Details Page

image

Add New Page

image

Edit Product Page

image

Delete Confirmation Page

image

Product List Page

image

For all the methods, I am doing console.log as shown below.

image

One of the things that tripped me off was on initial page load when model was null. I had to add *ngIf=”product” at the root div. So that’s all I could accomplish today. The code is pushed to github.

Next I am going to tackle form validation.

Sunday, June 10, 2018

A1–Building App using Angular and ASP.NET Core 2.1

This post is a part of a series of posts that I will write as I build an app using Angular and ASP.NET Core 2.1. My goal with this series is not to show you how to do something but to build something little everyday and write about it. If I don’t build anything then I don’t write about it. I believe in concept of learn via building and learn via sharing. So let’s combine these two concepts. Please expect lots of mistakes being made by me and I hope you will correct them.

I have lot of experience building apps using AngularJS and ASP.NET MVC 5 but I wanted to learn Angular latest and ASP.NET Core 2.1. What I have done so far in this journey is listed below, so you have some background and you don’t assume that I am smart.

1. Watched Angular: Getting Started course on Pluralsight by Deborah Kurata

2. Finished Angular Tutorial: Tour of Heroes

3. Watching Angular: Forms course on Pluralsight by Mark Zamoyta

4. Built an app to showcase products and stuff.

My environment looks like this

1. Visual Studio 2017 15.7.3

2. Powershell

3. VS Code Latest

4. ASP.NET Core 2.1

5. Angular cli version listed below

image

6. Angular versions 5.2.0

I wanted to have server side back-end technology as ASP.NET Core and wanted to combine Angular with it. In latest ASP.NET Core 2.1, there is a template for getting started with this type of thing.

image

After application project was created, I was excited and I wanted to create a new Angular component. I executed this command on the command line ng generate component product-list and got the friend message to run npm install first. So I ran npm install and then did ng generate component product/product-list and used to get some errors. I don’t recall. However, after deleting contents of node_modules folder it started working.

Tip: Don’t run npm install. Just click Run or hit F5 and let visual studio install all dependencies.

In earlier version of ASP.NET Core 2.0 runtime, creating components using Angular CLI wasn’t that straight forward. In 2.1 working with Angular Cli has been fixed. I like this.

By default when you run the application, you get counter page and fetch data page. The fetch data page shows you how to retrieve data from ASP.NET WEB API endpoint.

I want to create product related pages such as insert, edit, delete, list, details and use ASP.NET WEB API. So first I created Product controller and related methods for doing insert, edit, delete, list and details. I used attribute routing. For simplicity, I am not connecting it to any database. I just want working methods. Then I tested these methods using PostMan client. Below is my Product Controller.

 [Route("api/[controller]")]
    public class ProductController : Controller
    {
        private static List<Product> Products = new List<Product>() {
            new Product { Id = 1, Title = "XYZ1", Price = 1,ImageUrl = "ImageUrl_XYZ1" },
            new Product { Id = 2, Title = "XYZ2", Price = 2,ImageUrl = "ImageUrl_XYZ2" },
            new Product { Id = 3, Title = "XYZ3", Price = 3,ImageUrl = "ImageUrl_XYZ3" },
            new Product { Id = 4, Title = "XYZ4", Price = 4,ImageUrl = "ImageUrl_XYZ4" },
            new Product { Id = 5, Title = "XYZ5", Price = 5,ImageUrl = "ImageUrl_XYZ5" },
            new Product { Id = 6, Title = "XYZ6", Price = 6,ImageUrl = "ImageUrl_XYZ6" },
            new Product { Id = 7, Title = "XYZ7", Price = 7,ImageUrl = "ImageUrl_XYZ7" },
            new Product { Id = 8, Title = "XYZ8", Price = 8,ImageUrl = "ImageUrl_XYZ8" },
            new Product { Id = 9, Title = "XYZ9", Price = 9,ImageUrl = "ImageUrl_XYZ9" }
            
        };
        [HttpGet("[action]")]
        public IEnumerable<Product> List()
        {
            return Products;
        }

        [HttpGet("[action]/{id:int}")]        
        public ActionResult<Product> Find(int id)
        {
            var product = Products.Where(x => x.Id == id).FirstOrDefault();
            if (product != null)
            {
                return product;
            }
            return NotFound($"Product with id {id} was not found");
        }

        [HttpPost("[action]")]
        public ActionResult<Product> Edit([FromBody] Product product)
        {
            return product;
        }

        [HttpPost("[action]/{id:int}")]
        public ActionResult<Product> Delete(int id)
        {
            return Ok("Delete Successfull");
        }

        [HttpPost("[action]")]
        public ActionResult<Product> Insert([FromBody] Product product)
        {
            return product;
        }
    }

Next up, I tried to create product-list angular component using angular cli using command ng g c product/product-list. I wanted to create product related component inside product folder. Hence, I used product/product-list as my component’s name. I am just going to borrow code from fetch-data component to retrieve product list.

import { Component, OnInit, Inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Component({
  selector: 'app-product-list',
  templateUrl: './product-list.component.html',
  styleUrls: ['./product-list.component.css']
})
export class ProductListComponent implements OnInit {
  public products: Product[];
  constructor(http: HttpClient, @Inject('BASE_URL') baseUrl: string) {
    http.get<Product[]>(baseUrl + 'api/Product/List').subscribe(result => {
      this.products = result;
    }, error => console.log(error));
  }
  ngOnInit() {
  }
}
interface Product {
  id: number;
  title: string;
  price: number;
  imageUrl: string;
}

Next up, I hooked up navigation and you can see all the products being displayed. For brevity, I am not listing all the steps or code. I am going to put all this on GitHub so you can see the code and progress I make. Because, it turns out blogging every step is going to be time consuming. [edit- Github Repo here]

image

Creating angular components for delete, details, edit and insert as shown below.

image

image

Creating edit, delete, details, insert action buttons on product-list html page and adding routerLink so we can take appropriate actions. Below is how the page looks now.

Tip: Route should not have any ending /. Have product/insert instead of product/insert/

image

I hooked up these buttons with their respective components created in earlier step. Right now I have not created an markup for these individual action pages. That’s all I could get done today.

Next goal is to put this on GitHub and finish creating insert, edit, delete, details features of products page. See you next time. [edit- Github Repo here]

Friday, June 8, 2018

My Visual Studio 2019 Feature Wishlist

In this MSDN blog post, John Montgomery announced that the next version of Visual Studio is going to be 2019 and they have started planning for it. As I am very excited about this news, I couldn’t help myself from thinking about what features I would like to have in Visual Studio 2019. What could Microsoft add to VS that will make my job easier? So friends below is a list of features that are on my wish list.

1. Support for integrated terminal

Have you seen how snappy VS code is? It is light weight, fast and responsive. We need that kind of support for integrated terminal inside of Visual Studio 2019. The current option of right-clicking a node within Solution Explorer and clicking on open command prompt here is not ideal.

2. Auto Save

Alright, now you will say, “Mitul, you are saying copy all features from VS code and put in VS2019”. No. Not all the features but some things are really good in VS Code. I like auto save feature of VS Code and it just works. Can we have this in VS2019. Please…

3. Being able to easily add new files

When you hover in VS Code, you can see icons to add a new file, folder, refresh, and collapse all. This feature is very useful as it makes adding new files so much easier. I use Ctrl+F2 to invoke Add File Extension written by Mads Kristensen and this is one of my favorite extension but having this icon from VS code would be nice.

image

4. Command Window, Ctrl+Shift+P

In VS code when you hit Ctrl+Shift+P, you will see a command window appear and you can execute any command from there.

image

In VS, things are scattered around for doing these type of things such as,

1. Ctrl+Q

image

2. Ctrl+D

image

3. Command window

image

Can we have command execution workflow like VS code. You should be able to type command in english language instead of remember edit.somecommand.

5. Auto Download Next VS Update

We all appreciate the fast release cadence of VS but the yellow notification icon when it pops up every few days, it annoys me. When I see it, I want to update it. And this is good but I don’t like waiting for download. So can we have a setting where we can specify, “Always download new updates and prompt for update when done”. Download should happen in the background when new updates are available. I wish one day we can have silent VS updates in the background just like Chrome. I know this will be lot of work but may be some day in future. VS2019 may be..

6. Multi-cursor support

I have seen in some roadmap of VS2017 that multi-cursor support is coming. If it is not then we need multi-cursor support in VS2019.

7. Debugging - Support for Dump()

What is this Dump() method? If you have used LINQPad, then you will be familiar with Dump() method. In LINQPad you can put . after anything and call Dump() method and it will display the entire object in a nice format. It is so much easier to quickly hack up a script and get going. Let me show you something. In the image below, I called Dump() in many places to inspect different values and in the Results panel below you can see after each iteration those values were printed. “But Mitul how would this work in VS?”, you might ask. So let’s say if .Dump() was available then we can have it display these values in the output window. I imagine you could have an extension method in the Diagnostics assembly and display in output window.

image

8. Make animations and actions feel lightweight

Alright, this is highly subjective and you should remember that this is my wish list, so you might not feel the same way. What makes VS code light weight or feel light weight? When moving document to left or right it feels fast. There aren’t many animations in VS code whereas shifting documents within VS to left or right feels heavy. It would also be nice if there was keyboard support for docking documents within VS to left right or to next screen.

That’s all I have for now. We don’t want to list 10 features just to please OCD gods.

So what do you think about these features? Please leave a comment below and if I think of other feature ideas I will blog them again.

Enjoy day dreaming!

My Build 2018 Experience

I hate backpacks. Keep reading to find out why. I know its been a month since Build 2018 and I am late in writing this post but I didn’t wanted to feel guilty for not writing about my wonderful experience at Build 2018. So here you go.

I have attended 3 Build conferences one in 2013, 2016 and 2018. And I felt this was the best Build. After attending each Build, I felt that, that particular conference was the best conference. In this post, I want to reflect upon my experience attending Build 2018 conference. I traveled with family this year and so it wasn’t that lonely in Seattle. For my first conference, I was so excited to attend that I paid conference ticket using personal expense. After receiving Surface Pro tablet, I didn’t felt that bad. Past two conferences were all paid for by my company so it was awesome.

There are 386 Build 2018 videos. The content quality from Build is top notch. Every session is recorded and available online for later viewing and downloading. They have the ability to live stream sessions directly on Channel9 website. The work required to organize such a conference is beyond my imagination and I am always blown away by the scale of the conference. This brings me to one of the issues with Build this year. It was difficult to know where everything was. The build app was helpful in finding things and the app was much better than previous years. I later came to know that there were hands-on labs. Next time, I would recommend to spend few minutes just getting familiarized with conference layout so it becomes easier to find and locate a session.

Keynote

Keynote this year was about inspiring and selling us a vision about AI, Azure innovations, and intelligent Edge (ahem Windows). When you are standing in line with thousands of developers to watch keynote, you realize how big this conference is. The keynote hall was big and there were at least 8 insane size screens in the hall. So no matter where you got a seat you could not miss anything (unless you were on your phone). Over the past few conferences, I have noticed that more and more cool stuff is getting announced not in keynote but during the sessions. I feel there should be two mini keynotes detailing some common things that everyone should know.

Sessions

Sessions were action packed with high production quality content. Some of the sessions I attended and watched online are listed at the end of this post.  All the sessions are recorded and available on Ch9 and YouTube. I prefer YouTube and I want to thank ch9 team for putting it on YouTube. Due to YouTube Red, I downloaded sessions and was watching them while waiting at the airport and in flight. Another benefit of YouTube is that it will suggest you more Build 2018 videos. And because I forget to watch videos, after few days, I see a suggestion and I watch it.

Another pro tip for watching sessions

1. Download Build 2018 videos using PowerShell script

2. Use VLC media player to watch and quickly search videos. You will have to paste this link to the podcasts section and all the videos will appear on the right.

During the conference, when I was tired and didn’t felt like attending session, I was able to watch sessions on my phone that were live streamed while crashing on couch in the expo area.

Expo area

The expo area this year was huge. You are standing and walking most of the time and if you are carrying laptop in your backpack then it will wear you out. And I was tired like crazy. So that’s the reason why I hated carrying backpack. 

I was blown away by the presence of so many product/framework specific booth from Microsoft and of course from vendors and partners. I had the most fun interacting with Program Managers, Product Owners, and Engineers from Microsoft. Everyone greeted me very nicely. Some even approached me while I was just staring at the display TV or some chart saying, “Are you just going to stare at TV or ask me questions?”. Some went to great lengths—whiteboarding solutions, showing actual live demos and clearing my doubts. I learnt a lot by asking questions and talking to people. I could feel the openness, inclusiveness, curiosity in the culture. I did not wanted to leave Build because of this reason.

Since my last two Build, I have been spending more of my time in Expo area. This is the biggest benefit of attending a conference. Otherwise, you can watch keynote and sessions online. If you do not like talking to people then also attending in person has many benefits. For example, you can take picture with some legends—Scott Hanselman, Carl Franklin and Richard Campbell. In addition to that, this year we were able to pat dogs, horse and cats. I am not kidding there was an area with wooden fencing where you could pat dogs, horse and cats.

image

image

Booths visited

Windows admin center, PowerShell and Console Team, Eye Tracking, Adaptive Cards UI, TFS And VSTS, Branching and Release Management, Containers Team, Build Recap, Git branching insights, MSIX, MongoDB, .NET Platform, AI - ML.NET, Azure Functions, ASP.NET, Azure Essentials Training, AI School, Xamarin Essentials, IOT, Windows XAML, WinForms, Azure Resource Manager, Bot framework, ASP.NET Core, Launch Darkly

Food at Build

Alright, I know what you are expecting about food. It must be great, this and that. Food at conferences is mostly a miss and sometimes hit. During Build registration, there was an option for selecting Indian Vegetarian food. I was very excited after seeing this option. For the first two days, I couldn’t find Indian Vegetarian. It was there but it was located at a place that I came to know the last day. So its my fault for not discovering it and also it should have been placed in a more convenient location.

Closing thoughts

One of the things I was interested in was getting feedback from developers, program managers or anyone who has experience in software development about my career and my resume. And Build is the place where you have thousands of developers and leaders with years of experience in the field. I was literally carrying copies of my resume and asking few people about their opinion. Sometimes I felt shy and not confident in approaching people asking questions while they were busy with other folks. Well I developed courage and asked few individuals and got valuable piece of advice. I wish and humbly request Microsoft to dedicate a section where there would be mentors from software industry giving you advice regarding your career. Simple.

Everyone may not be able to attend this conference due to various reasons, I feel very lucky to have attended this three times. It was an honor and privilege to attend Build. I am thankful to University of Michigan for sending me.

List of Sessions attended or watched online.

Friday, April 27, 2018

Azure DevOps Project brings DevOps to everyone

So Azure has this cool feature called DevOps Project right and in this post, I want to show you what it is and why it is cool. At the time of this writing, this feature is still in preview so hang on to your seatbelts. When you click on this, you will be presented with two options—start fresh with a new application or start with your application. You can select any language. Let’s select .NET.

image

After selecting .NET, you have to decide framework—ASP.NET or ASP.NET Core. Let’s select ASP.NET.

image

Next, select where you want to host this app—inside azure app service or inside virtual machine. Let’s select Web App.

image

Final step, provide details regarding app, azure subscription, app name etc. and then click Done.

image

So what does this do for us behind the scenes? After the resources are successfully created, you will see something like this. Let’s understand all the things it has created for us.

image

1. Visual Team Services Account

2. Git repository (source code)

3. Build definition (CI)

4. Release definition (CD)

5. App Service (hosted website on Azure)

6. Application Insights (logging and monitoring)

It did all these things. One more thing, it also checked in code, ran build definition, created a release and deployed website to app service. Let’s say thank you to folks who created this for us. If you do not know how to create this end-to-end pipeline then you can create a DevOps project like this and inspect how different pieces work together. Azure is great for learning and great for experimentation, even if you do not have a single app hosted on Azure for production. DevOps is something every developer should be able to do it.

Let me know in the comments, what do you think about this feature.  

Sunday, January 21, 2018

Control multiple servos using Raspberry Pi 2 Model B, PCA9685, Windows 10 IOT and C#

In this post, I will be showing you how to control servos using Raspberry Pi 2 model B, Windows 10 IOT, C#, PCA9685 and Visual Studio 2017.  This post assumes you have some experience running C# application on a remote device. I will not cover how you connect to Rpi2 via Visual Studio or anything related to deployment. There is also an accompanying youtube video I have created and you can find it here - https://youtu.be/gkWYirX8uHo.  For code and power point check links below.

Servos motors typically turn 0 to 180 degrees. Some servos can go beyond 180 degree as well. The way you control servos is by providing a Pulse Width Modulation (PWM) signal. 

image


Raspberry Pi 2 has one hardware PWM pin and you can do software PWM via any of its GPIO pins.  If you want to control multiple servos then just one PWM hardware pin is not going to cut it and if you use GPIO pins and do PWM via software then you will not have enough GPIO pins for doing other work.  And PWM via software is also not that accurate. However, I am not too concerned about it for my project. 

So what are our options if we want to control multiple servos? Enter I2C protocol.  I2C is a protocol that enables master slave communication over SDA and SCL.  Via I2C you can have multiple devices (slaves) connect to our RPi2 (master) without taking up those GPIO pins. What does that mean? For example, if you see any sensor breakout boards that have I2C pins like SDA and SCL then you can connect multiple of those sensors directly to RPi2 via I2C. So we will use I2C pins of RPi2 to connect to PCA9685 chip which has 16 header pins that allow us to control up to 16 servos or 16 LEDs. With I2C and PCA9685 you can connect up to 62 PCA9685 boards and control up to 992 servos.

image

Let’s talk about PCA9685 and what it is.  The PCA9685 comes on a board typically if you buy from Adafruit or Amazon or any other retailer. I got mine from SunFounder via Amazon. The PCA9685 has 12-bit resolution. What does that mean? It means that it has a resolution of 2^12 = 4096. What does that mean? It means that for each period of your frequency you will have 4096 steps.  So let’s say your PWM frequency is 60Hz and 1/f is period T = 1/60s. T = 17ms. Now each 17ms is divided into 4096 steps. The time is taken per step is 17ms/4096=4.15us. If you want to give a pulse of 0.5ms then figure out how many steps are required.  Total Steps required for 0.5ms pulse = 0.5ms/4.15us = 120steps. Similarly you can find out steps required for 1ms,1.5ms,2ms,2.5ms. Below are the steps for these times.

0.0005 –> 120

0.0010 –> 240

0.0015 –> 361

0.0020 –> 481

0.0025 –> 602

How did I come up with these times and why do we need them? Typically servos turn 0 degrees if you provide a 0.5ms pulse, 1.0 for 60 degree pulse, 1.5ms for 90 degrees and 2.5ms for 180 degrees.  These are not accurate numbers and you find out these times for different servo motors. In our experiment we will fine tune our calculation so these turn servo exactly at a particular angle. Please see the section below where it says fine tuning our calculations so servo turn at our desired angle.

Now your next question is going to be how to turn servo at a specific angle other than 0,60,90 or 180.  In other words, if I want to turn servo at any random angle say 35 degrees, what is the number of steps we need to provide.

602-120 = 482 Total number of steps from 0 to 180 roughly.

480/180 = 2.7 Step per angle.

120 + 2.7x = Steps required to turn our servo at an angle x.

For 35 degrees,

120 + 2.7(35) = 214.5 Steps for 35 degrees.

Let’s summarize, to turn our servo at angle 35 degrees, we need to tell PCA9685 chip to turn the pulse HIGH for 214.5 steps and (4096-214.5) LOW.

image

Note: These calculations can change based upon your frequency and servo.  I am showing you this based upon Tower Pro SG90 micro servo motor at 60Hz frequency. Why 60Hz? Because this is a analog servo and analog servo you should have frequency ranging from 30Hz to 60Hz.

Since all the math is out of our way we can now focus other things.

1. Block diagram

In the block diagram, the things I haven’t shown are that Host PC and RPi2 are connected to their own keyboard, mouse and monitor.

image

2. Wiring diagram

The below image is from adafruit.com. Connecting multiple servos is pretty much straightforward.

raspberry_pi_ServoSketch

3. Coding

You are now really impatient to see the working code. Right. Every body seems to use Adafruit library provided in python.  The c# library from Adafruit i.e AdafruitClassLibrary available on nuget doesn’t work out of the box if you create a new UWP application in Visual Studio. Why? Because the it is just not updated and it has issues. So I copied Adafruit I2CBase.cs and PCA9685.cs classes and modified them so they will throw exceptions if anything goes wrong. The main page of the application has few textboxes and buttons to control servos.

You can find the source code at this github link.

Follow the steps to run the application.

1. Ensure that Platform is set to ARM and Build configuration to Debug

2. Start the Visual Studio debugger on RPi2. This you can start by the Device Portal under Debug menu.

3. Run the application and it will deploy to the device and the application will start. (For me debugging doesn’t work and a prompt appears and I close that prompt)

4. Once you have the application running you will see a UI as shown in the figure below.

5. Press InitPCA9685

6. Press 60 the Step 2 textbox and SetPWMFrequency

7. Then enter the desired angle for your servo say 30 degrees.

You can see some logging into the textblock as you are executing actions.

image

The line of code that actually sets the steps is actually very simple.

_pca9685.SetPin(0, ticks, false);
For 35 degree angle ticks are 214.5 ticks, the code sets the pin 0 (which is where the first servo is connected) to HIGH starting from 0th tick to 214.5 tick and turns it LOW from there on till 4095th tick.
4. Fine Tuning
If you have followed so far and found that servo horns do not go exactly from 0 to 180 then we will tackle it in this section. It either goes past 0 or beyond 180. So let’s try to fix it. 
a. Adjusting the lower and upper limit. 
Let’s Recap – Do you remember the values 120 and 602? I will wait. Go above and come back. Alright those are the only things that we need to alter. That will determine our angle equation. My values after adjustment are as follows: 
125 and 530
The resulting equation to calculate Ticks for a given angle is 
125+2.25*angle
Those two values are the biggest things.
b. Placing your servo horns
Placing your servo horns is important. The lower and upper bounds will be affected based upon how you place your servo horn. Normally I place servo horn after providing a zero pulse and mark the position. Sometimes the grove will not fit at the exact zero position. At this time you will have to modify the upper and lower tick values to fine tune that servo.  
c. Changing PWM frequency
All of our calculations were based upon 60Hz frequency. If you change this frequency then you will have to change recalculate everything again and do your tuning accordingly. 
Notes:
1. The angle of your servo will also depend on how you are mounting your servo horn. I would pulse the servo to zero’s position and then place the servo horn and fine tune the steps.
2. At some steps you will hear the servo is getting stuck. This is due to servo is not in the desired position. Adjust the tick plus or minus one and you will see that it doesn’t occur. This is where we need to tune our calculations. This is a trial and error process. 
3. Somehow I cannot debug the application while running using Visual Studio 2017. Hence I had to create UWP UI application with textboxes and buttons. You will need a monitor, keyboard, mouse connected to Rpi2 to enter the angle and visualize what is happening. 
4. If you would like to know all the components used in this then please refer the environment section.
Resources:
Below are the resources I have found to be useful while learning this process. 
1.  Adafruit Raspberry pi servo driver
2.  Sunfounder wiki
3.  PCA9685 datasheet
4.  AdafruitClassLibrary
5.  Full source code available here
6.  PowerPoint Slides
7.  YouTube Video Link

Environment

1. Windows IOT – 10.0.16299.125
2. Raspberry PI 2 Model B
3. Visual Studio 2017 Update 15.5
4. Power Supply for Raspberry PI 5V 2.1A
5. PCA9685 supplier (SunFounder)
6. Breadboard
7. Jumper wires
8. 5V Power Supply for PCA9685 (Eventtek Power Supply 0-30V 0-5A)
9. Host Computer OS (Windows 10)
10. Micro Servos (Tower Pro Micro Servo SG90)