How To Create SPA Using ASP.NET Core And Angular 2

Introduction
 
In my previous article "Build Your First ASP.NET MVC Core Application", I explained how to create the Application, using  ASP.NET Core and in my article “Build Your First Angular 2 Application With Type Script", I have explained how to create an Angular 2 Application, using TypeScript.
 
In this article, I will explain how to create SPA Application using an ASP.NET Core and Angular 2 with TypeScript.
 
Prerequisites

The following software needs to be installed in our system before starting the work.
  • .NET Core 1.1.
  • TypeScript 2.0.
  • Node JS version 6 or later.
  • Editor such as VS 2017 or VS Code.
The easiest way to create Angular SPA (Single Page Application) Application with an ASP.NET Core is to use project template. There are many project templates, which are are available on Nuget. To install SPA template, we need to run the command given below from the command prompt.
  1. dotnet new --install Microsoft.AspNetCore.SpaTemplates::*  
 
 
After successful installation of the templates, it lists down all the installed templates. We can use any installed template to create SPA.
 
 
 
Here, I want to create SPA, using MVC ASP.NET Core with Angular, so we need to execute the command given below, using the command prompt at the place, where you want to create an Application.
  1. dotnet new angular  
 
After successful creation of an Application, we need to download dependencies of an Angular 2 as well as an ASP.NET Core. To download the dependencies of Angular, we need to execute the command given below, using the command prompt. This command reads package.json file and download the dependencies.
  1. npm install  
Similarly, using the command given below, we can download the dependencies of an ASP.NET Core, which is defined in package.json (VS 2015) or .csproj file (VS 2017).
  1. dotnet restore  
 
Once all the project dependencies are installed and if we have an editor such as VS 2017, then we can run the project by pressing CTRL + F5.
Alternatively, we can run the project by running the command given below from the command prompt.
  1. dotnet run  
 
 
Output
 
 
 
Structure of the Project
 
When we look at the structure of the project, it contains the files related to configuration such as package.json, tsconfig.json and Angular project related files as well as ASP.NET Core MVC related files.
 
This project initially bootstraps as an ASP.NET Core MVC project by calling an index action method of Home controller. Index.cshtml file internally bootstraps an Angular component i.e. app.component.ts.
 
 
 
This project template puts all Angular related code in ClientApp folder. This folder also contains UI testing related configuration and the code.

Adding New Module in the project template
 
To add new module to this project, first we need to create new folder “MyDetails” under the ClientApp>> app>> Components folder.
Next step is to create module, component and template view.
 
 
 
mydetails.Component.ts 
  1. import { Component } from '@angular/core';  
  2.   
  3. @Component({  
  4.     selector: 'mydetails',  
  5.     templateUrl: './mydetails.Component.html'  
  6. })  
  7. export class MyDetailsComponent {  
  8.       
  9. }  
mydetails.Component.html
  1. <h1>  
  2.     Welcome to my details page.  
  3. </h1>  
The next step is to add navigation to navMenu component. I have added the code given below to navmenu.component.html file. Using routerLink Directive, we can link the specific parts of our Application. This Directive always gives the provided input as a delta to the current URL.
 
navmenu.component.html
  1. <li [routerLinkActive]="['link-active']">  
  2.         <a [routerLink]="['/my-detail']">  
  3.                 <span class='glyphicon glyphicon-link'></span> My New Link  
  4.         </a>  
  5. </li>  
The next step is to import this component to app.module (root module) and also define the path to router module. The router module contains two property paths (selector) and the component. The code is given below for app.module.ts file (Application root module).
 
app.module.ts
  1. import { NgModule } from '@angular/core';  
  2. import { RouterModule } from '@angular/router';  
  3. import { UniversalModule } from 'angular2-universal';  
  4. import { AppComponent } from './components/app/app.component'  
  5. import { NavMenuComponent } from './components/navmenu/navmenu.component';  
  6. import { HomeComponent } from './components/home/home.component';  
  7. import { FetchDataComponent } from './components/fetchdata/fetchdata.component';  
  8. import { CounterComponent } from './components/counter/counter.component';  
  9. import { MyDetailsComponent } from './components/myDetails/mydetails.Component';  
  10. import { FormsModule } from '@angular/forms';  
  11.   
  12. @NgModule({  
  13.     bootstrap: [ AppComponent ],  
  14.     declarations: [  
  15.         AppComponent,  
  16.         NavMenuComponent,  
  17.         CounterComponent,  
  18.         FetchDataComponent,  
  19.         HomeComponent,  
  20.         MyDetailsComponent  
  21.           
  22.     ],  
  23.     imports: [  
  24.         FormsModule,  
  25.         UniversalModule, // Must be first import. This automatically imports BrowserModule, HttpModule, and JsonpModule too.  
  26.         RouterModule.forRoot([  
  27.             { path: '', redirectTo: 'home', pathMatch: 'full' },  
  28.             { path: 'home', component: HomeComponent },  
  29.             { path: 'counter', component: CounterComponent },  
  30.             { path: 'fetch-data', component: FetchDataComponent },  
  31.             { path: 'my-detail', component: MyDetailsComponent },  
  32.             { path: '**', redirectTo: 'home' }  
  33.         ])  
  34.     ]  
  35. })  
  36. export class AppModule {  
  37. }  
Output

 
 
Let’s extend this example and fetch observable data from the Web API (MVC) and display it on the screen. Here, I have created a model named “Personal”. I am filling all the properties of this model in an action method of controller class name “MyDetailsController”. Following is the definition of Personal and MyDetailsController class.
 
Personal.cs
  1. namespace test  
  2. {  
  3.      public class Personal  
  4.         {  
  5.             public string FirstName { getset; }  
  6.             public string LastName { getset; }  
  7.             public string AdharNumber { getset; }  
  8.             public string Email { getset; }  
  9.             public string PhoneNumber { getset; }  
  10.         }  
  11. }  
MyDetailsController.cs
  1. using Microsoft.AspNetCore.Mvc;  
  2.   
  3. namespace test.Controllers  
  4. {  
  5.     [Route("api/[controller]")]  
  6.     public class MyDetailsController : Controller  
  7.     {  
  8.         static Personal _personal = new Personal {  
  9.                 FirstName = "Jignesh",  
  10.                 LastName = "Trivedi",  
  11.                 AdharNumber = "45454 4545 55",  
  12.                 Email = "test@gmail.com",  
  13.                 PhoneNumber = "988988989"  
  14.             };  
  15.          
  16.         [HttpGet("[action]")]  
  17.         public Personal Mydetails()  
  18.         {  
  19.             return _personal;  
  20.         }  
  21.     }  
  22. }  
For client side, bind the data and I have created class named “Personal”. It contains same properties as Server side class.
 
mydetails.model.ts
  1. export class Personal {  
  2.     firstName: string;  
  3.     lastName: string;  
  4.     adharNumber: string;  
  5.     email: string;  
  6.     phoneNumber: string  
  7. }  
The next step is to create a Service. This Service retrieves from Web API (MVC), using http Service and the GetData method of this servicereturn observable of the Personal data. This observable stream can be published by any source. The subscription is required to specify the actions to be taken when the Web request processes the success or fail event.
 
mydetails.Services.ts
  1. import { Injectable } from '@angular/core';  
  2. import { Http, Response, RequestOptions,Headers } from '@angular/http';  
  3. import { Observable } from 'rxjs/Observable';  
  4. import 'rxjs/add/operator/map';  
  5.   
  6. import { Personal } from './mydetails.model'  
  7.   
  8. @Injectable()  
  9. export class MyDetailService {  
  10.     public personalDetail: Personal;  
  11.     public headers: Headers  
  12.     constructor(private http: Http) {  
  13.         this.headers = new Headers();  
  14.         this.headers.append('Content-Type''application/json');  
  15.     }  
  16.   
  17.     GetData(): Observable<Personal> {  
  18.         let person$ = this.http.get('/api/MyDetails/Mydetails').map(response => response.json());  
  19.         return person$;  
  20.     }  
  21. }  
Now, I am injecting this Service into the component and calling Service‘s Getdata method. Here, I have subscribes the success event and copied Service return data to the local variable.
 
mydetails.Component.ts
  1. import { Component } from '@angular/core';  
  2.   
  3. import { MyDetailService } from './mydetails.services'  
  4. import { Personal } from './mydetails.model';  
  5.   
  6. @Component({  
  7.     selector: 'mydetail',  
  8.     templateUrl: './mydetails.Component.html',  
  9.     providers: [MyDetailService],  
  10.     styleUrls: ['./myDetails.component.css']  
  11. })  
  12. export class MyDetailsComponent {  
  13.     public personalDetail: Personal = new Personal();  
  14.   
  15.     constructor(private myDetailService: MyDetailService) {  
  16.         this.myDetailService.GetData().subscribe(data => {  
  17.             this.personalDetail = data;   
  18.         });  
  19.     }  
  20. }  
To display the data, I have made some changes to the template view of the component.
 
mydetails.Component.html
  1. <h1>  
  2.     Welcome to my details page.  
  3. </h1>  
  4. <table>  
  5.     <tr>  
  6.         <td><strong> First Name : </strong></td>  
  7.         <td><input [(ngModel)]="personalDetail.firstName"/> </td>  
  8.     </tr>  
  9.     <tr>  
  10.         <td><strong> Last Name : </strong></td>  
  11.         <td><input [(ngModel)]="personalDetail.lastName"/> </td>  
  12.     </tr>  
  13.     <tr>  
  14.         <td><strong> Adhar Number : </strong></td>  
  15.         <td><input [(ngModel)]="personalDetail.adharNumber"/> </td>  
  16.     </tr>  
  17.     <tr>  
  18.         <td><strong> Email : </strong></td>  
  19.         <td><input [(ngModel)]="personalDetail.email"/> </td>  
  20.     </tr>  
  21.     <tr>  
  22.         <td><strong> Phone Number : </strong></td>  
  23.         <td><input [(ngModel)]="personalDetail.phoneNumber"/> </td>  
  24.     </tr>  
  25.     <tr>  
  26.         <td colspan="2"><input type="button" value="Save" (click)="save()" /></td>  
  27.     </tr>  
  28. </table>  
Also, add some style to the template view of the component.
 
myDetails.component.css
  1. td{  
  2.     padding-top: 10px;  
  3. }  
Now, I am re-running the Application. Here whatever data is coming from the Server (Web API), it displays on a screen.
 
Output
 
 
 
Summary

In this article, we learnt how to create SPA Application, using an ASP.NET Core and an Angular 2. Also, we learnt how to get observable data and bind to the template.