Angular 7 SPA CRUD With ASP.NET Core And Entity Framework Core

It feels good to be back with the 18th article on Angular and that too with Angular 7 which is out recently.

It feels great to be back with this, my 18th article on Angular with the recently updated Angular 7. With this article, let's try to explore the Angular 7 features and get hands on with the CRUD operations using Angular 7, .NET Core, and Entity Framework Core. Let us first set the agenda for this article.
 
Agenda
  1. Introduction to Angular 7

    1. New Features
    2. Angular CLI Changes
    3. Angular Material Changes
    4. Upgrading to Angular 7

  2. Adding New Project

  3. Front-end design and implementation using Angular 7

    1. Adding Components
    2. Adding Models and Config files
    3. Adding Bootstrap popups
    4. Adding Data service

  4. Back-end Web API Development using ASP.NET Core and Entity Framework Core

    1. Set up .NET Core project
    2. Setup Entity framework core
    3. Set up CORS to allow cross-origin resource sharing.

  5. Future expansion of this article

  6. Source code link
Angular 7
 
Finally, the wait for Angular 7 is over!! This version of the Angular has given us some exciting features. Primarily, the changes are in Angular Core, CLI, and then Angular Material. Let's explore it one by one.

Angular Core Changes
 
Some of the added features in the Angular Core are listed down here.
  1. Introduced new interface - UrlSegment [] to CanLoad interface
  2. New Interface DoBootStrap
  3. Added a new elements features - enable Shadow DOM v1 and slots
  4. Added a new router features - warn if navigation triggered outside Angular zone
  5. Added a new ability to recover from malformed URLs
  6. Added a new compiler support dot (.) in import statements and avoid a crash in ngc-wrapped
  7. Added a new "original" placeholder value on extracted XMB
  8. Updated dependencies to support TypeScript 3.1, RxJS 6.3 and Node 10.
Angular CLI Changes

CLI Prompts 
Angular 7 CLI has some exciting feature like prompt as shown in the screen below. This lets you set up the Angular project with a couple of questions.
Angular 7 SPA CRUD With ASP.NET Core And Entity Framework Core
 
Angular Material and CDK
 
Angular Material and CDK have come out with new advanced features like virtual scrolling and Drag and Drop. Let’s explore them in brief
 
Virtual Scrolling
 
This allows us to use the noticeable aspect of the list to load and unload the DOM element in the page. That means if we have a large chunk of the data and we want to show it in the list, we can make use of this feature.
 
Drag and Drop
 
"Drag and Drop" gets the support from CDK and includes the features like automatic rendering as the user moves items and including the helper methods for the record or transfer of items in the lists.
 
Application performance
 
Everything revolves around the application and Google has invested plenty of things and introduced some features which will help us to boost the performance . The first one is the Bundle Budget which lets us set the application bundle size and gives some errors when the limit is exceeded. The default size for bundle budget is 2 MB which can be increased later.
 
The next thing is the removal of the Pollyfill.ts file which is used only during the development. Now, it gets removed from the production automatically.
 
Upgrading to Angular 7
 
Well, many of us have the project built on the older versions of Angular. In order to upgrade the old versions to the new one, the official website has provided the ways and the detailed explanation of how to do that. You can find it here.
 
If we are migrating from the Angular 6 to Angular 7, the following command will do the work for us.
 
ng update @angular/cli @angular/core
 
So far, we learned about Angular 7 features and upgrading. Now, let's have some real action and add the project.
 
Adding New Project
 
To add an Angular project, we have some prerequisites to proceed further with this article.
  1. Installing latest Node.js
    This will install the NPM (Node package manager) and download all the dependencies or packages for our application. The latest version of the Node.js can be found here.

  2. Getting Angular CLI
    Once we are done with Node.js and NPM, the next step will be to download Angular CLI which will help us in setting up the things quickly. For installing CLI, we will need the following command.

    npm install -g @angular/cli

  3. Getting Visual Studio Code
    This is the IDE that we will be using in this article and for installing this, you can find the latest version of this right here.
Creating a new project
 
Now, it's time to add a new project with Angular 7. For this, let’s follow the steps as below in the figure.
 
Angular 7 SPA CRUD With ASP.NET Core And Entity Framework Core 
  1. Create the Directory where you want to save the project
  2. Use command ng New Angular7CRUDDemo
  3. Choose the proper option to add the Routing and CSS
Note
Depending on your machine and internet speed, it may take some time to download the package and project is ready.
 
Once the project is ready, let's open it from the File menu and we can see the directory structure, like below.
 
Angular 7 SPA CRUD With ASP.NET Core And Entity Framework Core 
 
One change we can see from the old version is the addition of the app-routing file which is added from the CLI prompt options while setting up the project.
 
Now, the question is how can we check if our project is Angular 7 compatible. For that, we need to check the package.json file which has the structure as below.
 
Angular 7 SPA CRUD With ASP.NET Core And Entity Framework Core 
 
When we see the highlighted section, we can say that the current project is configured to use the latest version of Angular dependencies.
 
Now, it is time for actual coding. We have divided our coding part into 2 sections - the first one being the UI in Angular 7 and the second one is Web API part in .NET Core and Entity Framework Core. Let us first see the UI part and then, we will see the Web API part with .NET  Core and Entity Framework core
 
Front-end design and implementation using Angular
 
As we all know the front-end or any Angular application is made up of the components, let’s see what will be the structure of the application. Before that, we should understand what we are going to achieve in this article.
 
Here, we are going to add the demo application which will be used to list, add, update, and delete the employees. For that, we will have the following directory structure.
 
Angular 7 SPA CRUD With ASP.NET Core And Entity Framework Core 
 
Above is the directory structure of the application where we have 7 components namely -
  1. Angular-crud.component.ts
    This is the component which will list down all the employees and will hold other components.

  2. employee-add.component.ts
    This is the component to create the employee record.

  3. app.component.ts
    This is the app component where all the components will be loaded through <router-outlet></router-outlet>.

  4. Employeeupdate.component.ts
    This is responsible for handling the Edit operation of the Employee record.

  5. DataService.ts
    This will hold all the API calls with various verbs using the Httpclient in Angular 7.

  6. Data Models
    This folder holds the Employee data model which will be the base for all and the config.ts file which will hold the configuration related data.

  7. App-routing.module.ts
    This is the Router which will be added to the application while configuring the project.
Let’s explore these components one by one.
 
Code Description
 
employee-Add.component.ts
  1. import { Component, OnInit,Input, ViewChild, ElementRef, EventEmitter, Output } from '@angular/core';  
  2. import { NgForm } from '@angular/forms';  
  3. import { Employee } from 'src/Models/Employee';  
  4. import { Router } from '@angular/router';  
  5. import {EmployeeDataService} from '../DataService/EmployeeDataService'  
  6. @Component({  
  7.   selector: 'app-employee-add',  
  8.   templateUrl: './employee-add.component.html',  
  9.   styleUrls: ['./employee-add.component.sass']  
  10. })  
  11. export class EmployeeAddComponent implements OnInit {  
  12.     
  13.   @Input()  cleardata: boolean = false;  
  14.   @Output() nameEvent = new EventEmitter<string>();  
  15.   objtempemp:Employee;  
  16.   @Input() objemp :Employee=new Employee();;  
  17.   @ViewChild('closeBtn') cb: ElementRef;  
  18. constructor(private dataservice:EmployeeDataService,private route:Router) {  
  19.    
  20.  }  
  21.  ngOnInit() {  
  22.   }  
  23.  Register(regForm:NgForm){    
  24.     this.objtempemp=new Employee();  
  25.     this.objtempemp.email=regForm.value.email;  
  26.     this.objtempemp.firstname=regForm.value.firstname;  
  27.     this.objtempemp.lastname=regForm.value.lastname;  
  28.     this.objtempemp.gender=regForm.value.gender;  
  29.       
  30.   this.dataservice.AddEmployee(this.objtempemp).subscribe(res=>{  
  31.     alert("Employee Added successfully");  
  32.     this.TakeHome();  
  33. }  
  34.   )  
  35.   }   
  36.   TakeHome(){  
  37.     this.nameEvent.emit("ccc");  
  38.     this.cb.nativeElement.click();  
  39.     this.route.navigateByUrl('');  
  40.   }  
  41. }  
Employee-add.component.html
  1. <div class="container" style="border:thin">  
  2. <form #empadd='ngForm' (ngSubmit)="Register(empadd)" class="form-horizontal" style="width:50%"  >    
  3. <div class="form-group" >  
  4.             <label class="control-label col-sm-2" for="fname" >First Name:</label>  
  5.             <div class="col-sm-10">  
  6.               <input  style="width:50%"    type="text" class="form-control"  
  7.                width="50%" id="fname" placeholder="Enter first name"  
  8.                name="firstname" firstname required [(ngModel)]='objemp.firstname'  #firstname="ngModel">  
  9.            <span class="help-bpx" *ngIf="firstname.touched && !firstname.valid ">Required</span>  
  10.             </div>  
  11.           </div>  
  12.           <div class="form-group" >  
  13.             <label class="control-label col-sm-2" for="email">Last Name:</label>  
  14.             <div class="col-sm-10">  
  15.               <input style="width:50%"   required type="text" class="form-control" width="50%"   
  16.               id="lastname" placeholder="Enter Last Name" name="lastname" lastname required [(ngModel)]='objemp.lastname'  #lastname="ngModel">  
  17.               <span class="help-bpx" *ngIf="lastname.touched && !lastname.valid ">Required</span>  
  18.             </div>   
  19.           </div>  
  20.           <div class="form-group" >  
  21.             <label class="control-label col-sm-2" for="Gender">Gender:</label>  
  22.             <div class="col-sm-10">  
  23.               <select name="gender" gender required [(ngModel)]='objemp.gender'  #gender="ngModel">  
  24.               <option value="0" selected disabled>Please Select</option>  
  25.               <option value="1">Male</option>  
  26.               <option value="2">Female</option>  
  27.               <span class="help-bpx" *ngIf="gender.touched && !gender.valid ">required</span>  
  28.             </select>  
  29.             </div>  
  30.           </div>  
  31.           <div class="form-group" >  
  32.             <label class="control-label col-sm-2" for="email">Email:</label>  
  33.             <div class="col-sm-10">  
  34.               <input #email="ngModel"  style="width:50%" type="email" [(ngModel)]='objemp.email' class="form-control" width="50%" id="email" placeholder="Enter email" name="email">  
  35.               <span class="help-bpx" *ngIf="email.touched && !email.valid ">**</span>  
  36.             </div>  
  37.           </div>  
  38.            <div class="form-group">          
  39.             <div class="col-sm-offset-2 col-sm-10">  
  40.               <button  id="btnsubmit"  type="submit" class="btn btn-primary">Submit</button>  
  41.             </div>  
  42.           </div>  
  43.         </form>  
  44.       </div>  
  45.       <button style="display:none" type="button" #closeBtn  class="btn btn-default"   data-dismiss="modal">Close</button>  
Above is the code for the Employee Add Component and template for the same.
 
Code Description
  1. In this code, we have the import section which is needed for the app.
  2. In Constructor, we have injected the data service and the Router.
  3. We have a function Register(regForm:NgForm ). Here, we are using the template-driven approach for adding an employee. So, we have declared the form object of type NgForm.
  4. In this method, we are subscribing the Addemployee Data service. On the success, we are showing the alert and redirecting the route to the Home component.
  5. We have a TakeHome method that will emit the method to refresh the parent component and reload the data from there.

    In Template, we have added the Form tag and named the form as #empadd here in this. On NgSubmit event of the form, we are calling the Register() which will submit the form along with its values.

  6. For Validation purposes, we are using basic HTML validation.
  7. In the last line, we have added the code for the Close button which is dummy code and will be fired in the template when the Employee is added successfully.
This is about the Add Component. Let's see the Update component and its template which has the same structure and description as that of the Add Component.
 
employeeupdate.component.ts
  1. import { Component, OnInit, ViewChild, Input, EventEmitter, Output, ElementRef } from '@angular/core';  
  2. import { EmployeeDataService } from '../DataService/EmployeeDataService';  
  3. import { Router } from '@angular/router';  
  4. import { NgForm } from '@angular/forms';  
  5. import { Employee } from 'src/Models/Employee';  
  6. @Component({  
  7.   selector: 'app-employeeupdate',  
  8.   templateUrl: './employeeupdate.component.html',  
  9.   styleUrls: ['./employeeupdate.component.sass']  
  10. })  
  11. export class EmployeeupdateComponent implements OnInit  
  12.  {  
  13.   constructor(private dataservice:EmployeeDataService,private route:Router) {  
  14.   }  
  15.   @Output() nameEvent = new EventEmitter<string>();  
  16.   @ViewChild('closeBtn') cb: ElementRef;  
  17.   ngOnInit() {  
  18.   }  
  19.   @Input() reset:boolean = false;  
  20.   @ViewChild('regForm') myForm: NgForm;  
  21.   @Input() isReset: boolean = false;  
  22.   objtempemp:Employee;  
  23.   @Input() objemp :Employee=new Employee();  
  24.   EditEmployee(regForm:NgForm)  
  25.   {  
  26.     this.dataservice.EditEmployee(this.objemp).subscribe(res=>  
  27.       {  
  28.       alert("Employee updated successfully");  
  29.       this.nameEvent.emit("ccc");  
  30.       this.cb.nativeElement.click();  
  31.        
  32.       },  
  33.   };  
  34. }  
employeeupdate.component.html
  1. <div class="container" style="border:thin">  
  2.   <form #EditForm='ngForm' name="editform" (ngSubmit)="EditEmployee(EditForm)" class="form-horizontal" style="width:50%">  
  3.     <div class="form-group">  
  4.       <label class="control-label col-sm-2" for="fname">First Name:</label>  
  5.       <div class="col-sm-10">  
  6.         <input style="width:50%" type="text" class="form-control" width="50%" id="fname" placeholder="Enter first name"  
  7.           name="firstname" firstname required [(ngModel)]='objemp.firstname' #firstname="ngModel">  
  8.         <span class="help-bpx" *ngIf="firstname.touched && !firstname.valid ">Required</span>  
  9.       </div>  
  10.     </div>  
  11.     <div class="form-group">  
  12.       <label class="control-label col-sm-2" for="email">Last Name:</label>  
  13.       <div class="col-sm-10">  
  14.         <input style="width:50%" required type="text" class="form-control" width="50%" id="lastname" placeholder="Enter Last Name"  
  15.           name="lastname" lastname required [(ngModel)]='objemp.lastname' #lastname="ngModel">  
  16.         <span class="help-bpx" *ngIf="lastname.touched && !lastname.valid ">Required</span>  
  17.       </div>  
  18.     </div>  
  19.     <div class="form-group">  
  20.       <label class="control-label col-sm-2" for="Gender">Gender:</label>  
  21.       <div class="col-sm-10">  
  22.         <select name="gender" gender required [(ngModel)]='objemp.gender' #gender="ngModel">  
  23.           <option value="0" selected disabled>Please Select</option>  
  24.           <option value="1">Male</option>  
  25.           <option value="2">Female</option>  
  26.           <span class="help-bpx" *ngIf="gender.touched && !gender.valid ">required</span>  
  27.         </select>  
  28.       </div>  
  29.     </div>  
  30.     <div class="form-group">  
  31.       <label class="control-label col-sm-2" for="email">Email:</label>  
  32.       <div class="col-sm-10">  
  33.         <input #email="ngModel" style="width:50%" type="email" [(ngModel)]='objemp.email' class="form-control" width="50%"  
  34.           id="email" placeholder="Enter email" name="email">  
  35.         <span class="help-bpx" *ngIf="email.touched && !email.valid ">**</span>  
  36.       </div>  
  37.     </div>  
  38.     <div class="form-group">  
  39.       <div class="col-sm-offset-2 col-sm-10">  
  40.         <button type="submit" class="btn btn-primary">Submit</button>  
  41.       </div>  
  42.     </div>  
  43.   </form>  
  44. </div>  
  45. <button style="display:none" type="button" #closeBtn class="btn btn-default" data-dismiss="modal">Close</button>  
Above is the code for the employee update component. Again, the description of this component is the same as that of the Add Component. Let's explore the List component for clarity.
 
Employeelist.component.ts
  1.  import { Component, OnInit, ViewChild } from '@angular/core';  
  2. import { EmployeeAddComponent } from '../employee-add/employee-add.component';  
  3. import { EmployeeDataService } from '../DataService/EmployeeDataService'  
  4. import { Employee } from 'src/Models/Employee'  
  5. import { Router } from '@angular/router';  
  6. import { EmployeeupdateComponent } from '../employeeupdate/employeeupdate.component';  
  7. @Component({  
  8.   selector: 'app-angular-crud',  
  9.   templateUrl: './angular-crud.component.html',  
  10.   styleUrls: ['./angular-crud.component.sass']  
  11. })  
  12. export class AngularCRUDComponent implements OnInit {  
  13.   
  14.   emplist: Employee[];  
  15.   dataavailbale: Boolean = false;  
  16.   tempemp: Employee  
  17.   
  18.   constructor(private dataservce: EmployeeDataService, private route: Router) {  
  19.   }  
  20.   ngOnInit() {  
  21.     this.LoadData();  
  22.   }  
  23.   LoadData() {  
  24.     this.dataservce.getEmployee().subscribe((tempdate) => {  
  25.       this.emplist = tempdate;  
  26.       console.log(this.emplist);  
  27.       if (this.emplist.length > 0) {  
  28.         this.dataavailbale = true;  
  29.       }  
  30.       else {  
  31.         this.dataavailbale = false;  
  32.       }  
  33.     }  
  34.     )  
  35.       , err => {  
  36.         console.log(err);  
  37.       }  
  38.   }  
  39.   deleteconfirmation(id: string) {  
  40.   
  41.     if (confirm("Are you sure you want to delete this ?")) {  
  42.       this.tempemp = new Employee();  
  43.       this.tempemp.id = id;  
  44.       this.dataservce.DeleteEmployee(this.tempemp).subscribe(res => {  
  45.         alert("Deleted successfully !!!");  
  46.         this.LoadData();  
  47.       })  
  48.     }  
  49.   }  
  50.   @ViewChild('empadd') addcomponent: EmployeeAddComponent  
  51.   @ViewChild('regForm') editcomponent: EmployeeupdateComponent  
  52.   loadAddnew() {  
  53.     this.addcomponent.objemp.email = ""  
  54.     this.addcomponent.objemp.firstname = ""  
  55.     this.addcomponent.objemp.lastname = ""  
  56.     this.addcomponent.objemp.id = ""  
  57.     this.addcomponent.objemp.gender = 0  
  58.   }  
  59.   loadnewForm(id: string, email: string, firstname: string, lastname: string, gender: number) {  
  60.     console.log(gender);  
  61.     this.editcomponent.objemp.email = email  
  62.     this.editcomponent.objemp.firstname = firstname  
  63.     this.editcomponent.objemp.lastname = lastname  
  64.     this.editcomponent.objemp.id = id  
  65.     this.editcomponent.objemp.gender = gender  
  66.   }  
  67.   RefreshData() {  
  68.     this.LoadData();  
  69.   }  
  70. }  
EmployeeList.html
  1. <div class="container">  
  2.   <input type="button" class="btn btn-primary" (click)="loadAddnew()" data-toggle="modal" data-target="#myModal" value="Create New">  
  3.   <hr>  
  4.   <div *ngIf="!dataavailbale">  
  5.   
  6.     <h4> No Employee Data is present Click Add new to add Data.</h4>  
  7.   </div>  
  8.   
  9.   <table class="table" *ngIf="dataavailbale">  
  10.     <thead>  
  11.       <tr>  
  12.         <th scope="col">Sr.No</th>  
  13.         <th scope="col">First name</th>  
  14.         <th scope="col">Last Name</th>  
  15.         <th scope="col">Email</th>  
  16.         <th scope="col">Gender</th>  
  17.         <th scope="col" style="align-content: center">Action</th>  
  18.       </tr>  
  19.     </thead>  
  20.     <tbody>  
  21.       <tr *ngFor="let e of emplist let i = index ">  
  22.         <td scope="col">{{i+1}}</td>  
  23.         <td scope="col">{{e.fname}}</td>  
  24.         <td scope="col">{{e.lname}}</td>  
  25.         <td scope="col">{{e.email}}</td>  
  26.         <td scope="col">{{e.gender=="1"?'Male':'Female'}}</td>  
  27.         <td style="display:none">{{e.id}}</td>  
  28.         <td scope="col">  
  29.           <button type="button" class="btn btn-default btn-primary" (click)="loadnewForm(e.id,e.email,e.fname,e.lname,e.gender)"  
  30.             data-toggle="modal" data-target="#myModaledit">  
  31.             <span class="glyphicon glyphicon-edit"></span> Edit  
  32.           </button>  
  33.           |  
  34.           <button type="button" class="btn btn-default btn-danger" (click)="deleteconfirmation(e.id)">  
  35.             <span class="glyphicon glyphicon-trash"></span> Delete  
  36.           </button>  
  37.   
  38.         </td>  
  39.       </tr>  
  40.     </tbody>  
  41.   </table>  
  42.   
  43.   <div id="myModal" class="modal fade" role="dialog">  
  44.     <div class="modal-dialog">  
  45.       <div class="modal-content">  
  46.         <div class="modal-header">  
  47.           <button type="button" class="close" data-dismiss="modal">×</button>  
  48.           <h4 class="modal-primary">Employee Add</h4>  
  49.         </div>  
  50.         <div class="modal-body">  
  51.   
  52.           <app-employee-add #empadd (nameEvent)="RefreshData($event)"></app-employee-add>  
  53.   
  54.         </div>  
  55.         <div class="modal-footer">  
  56.           <button type="button" #closeBtn class="btn btn-danger" data-dismiss="modal">Close</button>  
  57.         </div>  
  58.       </div>  
  59.   
  60.     </div>  
  61.   </div>  
  62.   
  63.   <div id="myModaledit" class="modal fade" role="dialog">  
  64.     <div class="modal-dialog">  
  65.       <div class="modal-content">  
  66.         <div class="modal-header">  
  67.           <button type="button" class="close" data-dismiss="modal">×</button>  
  68.           <h4 class="modal-title">Edit</h4>  
  69.         </div>  
  70.         <div class="modal-body">  
  71.           <app-employeeupdate (nameEvent)="RefreshData($event)" [isReset]="resetForm" #regForm></app-employeeupdate>  
  72.         </div>  
  73.         <div class="modal-footer">  
  74.           <button type="button" class="btn btn-danger" data-dismiss="modal">Close</button>  
  75.         </div>  
  76.       </div>  
  77.   
  78.     </div>  
  79.   </div>  
Code Description
  1. We are doing some import package that we needed in the component.
  2. We have declared the variables as per the requirement and in the constructor, we have imported the Data service and the Router.

    Following are the things which get us the reference of the child component added to the Parent component, i.e., the Employee list component.
    1. @ViewChild('empadd') addcomponent: EmployeeAddComponent  
    2. @ViewChild('regForm') editcomponent: EmployeeupdateComponent 
    Why do we will need this? Let’s see in the next two functions - loadAddnew(), loadAddnewForm(). We are using these two viewChild elements where we are resetting and setting the values of the particular form.

  3. Next thing we have is the LoadData(). It subscribes the get method in the data service and assigns the data to the employee list object we have.

  4. Delete Employee is called which takes the id from the Table Above and then call the delete service from the Data service and then show an alert if it successfully deletes the Employee Data from the database.

  5. Template code is simply displaying the list of the employees and added. The add and edit components in the code will render in the Popup.
After components, let's explore rest of the UI and front-end part.
 
Adding Models and Config File
 
Employee.ts
  1. export class  Employee{  
  2.    firstname:string;  
  3.    lastname:string ;  
  4.    email:string;  
  5.    gender:number;  
  6.    id:string  
  7.   
  8. }  
Here is the class which we will use in overall application to send and receive data.
 
Config.ts
 
This class will hold the Configuration related data. Right now we have only the App URL in the class but we can have rest of the data here.
 
Adding Bootstrap popups
 
We are using the Popups to show the Add and Edit form so to do this we have the code defined in the Employee List components template.
  1.    <div id="myModal" class="modal fade" role="dialog">  
  2.     <div class="modal-dialog">  
  3.       <div class="modal-content">  
  4.         <div class="modal-header">  
  5.           <button type="button" class="close" data-dismiss="modal">×</button>  
  6.           <h4 class="modal-primary">Employee Add</h4>  
  7.         </div>  
  8.         <div class="modal-body">  
  9. <app-employee-add #empadd (nameEvent)="RefreshData($event)"></app-employee-add>  
  10.         </div>  
  11.         <div class="modal-footer">  
  12.           <button type="button" #closeBtn class="btn btn-danger" data-dismiss="modal">Close</button>  
  13.         </div>  
  14.       </div>  
  15.   
  16.     </div>  
  17.   </div>  
In this we have used the normal Popup code and inside the modal-body we have rendered out child componets.
 
Adding Data service
 
Data service is the layer where we have separated the service calling logic from the rest of the application. Our data service looks like below,
  1. import { HttpClient, HttpParams, HttpHeaders } from '@angular/common/http';  
  2. import { Injectable } from '@angular/core';  
  3. import { Employee } from 'src/Models/Employee'  
  4. import { ROOT_URL } from 'src/Models/Config'  
  5. import { Observable } from 'rxjs';  
  6. @Injectable()  
  7. export class EmployeeDataService {  
  8.   employees: Observable<Employee[]>;  
  9.   newemployee: Employee;  
  10.   constructor(private http: HttpClient) {  
  11.   
  12.   }  
  13.   
  14.   getEmployee() {  
  15.     return this.http.get<Employee[]>(ROOT_URL + 'Employees');  
  16.   }  
  17.   AddEmployee(emp: Employee) {  
  18.   
  19.     const headers = new HttpHeaders().set('content-type''application/json');  
  20.     var body = {  
  21.       Fname: emp.firstname, Lname: emp.lastname, Email: emp.email, gender: emp.gender  
  22.     }  
  23.     console.log(ROOT_URL);  
  24.   
  25.     return this.http.post<Employee>(ROOT_URL + '/Employees', body, { headers });  
  26.   
  27.   }  
  28.   
  29.   ///  
  30.   EditEmployee(emp: Employee) {  
  31.     console.log(emp);  
  32.     const params = new HttpParams().set('ID', emp.id);  
  33.     const headers = new HttpHeaders().set('content-type''application/json');  
  34.     var body = {  
  35.       Fname: emp.firstname, Lname: emp.lastname, Email: emp.email, ID: emp.id  
  36.       , gender: emp.gender  
  37.     }  
  38.     return this.http.put<Employee>(ROOT_URL + 'Employees/' + emp.id, body, { headers, params })  
  39.   
  40.   }  
  41.   DeleteEmployee(emp: Employee) {  
  42.     const params = new HttpParams().set('ID', emp.id);  
  43.     const headers = new HttpHeaders().set('content-type''application/json');  
  44.     var body = {  
  45.       Fname: emp.firstname, Lname: emp.lastname, Email: emp.email, ID: emp.id  
  46.     }  
  47.     return this.http.delete<Employee>(ROOT_URL + '/Employees/' + emp.id)  
  48.   
  49.   }  
  50.   
  51. }  
In this we have all the methods which will make use of the Httpclient and Return the observable for each of the Basic HTTP verb like Get, Put, Post and delete. We have imported the basic Http essentials at the Top like HttpParams and HttpClient which is the part of the Angular/Common/http
 
So far we are done with the front-end design and Implementations of the things, so let’s move to the server side setup which is done using the .net Core and Entity Framework core so let’s have a look into it.
 
Back-end Web API Development using Asp.net Core and Entity Framework Core
 
In this section let’s explore the API which we use for the implementations of the CRUD operation for the employee. This section can be broken down into 4 sections. Mainly these are how we set up the ..NET Core project, then setting up the entity framework core, and then adding the CORS ( Cross-origin resource sharing ) section so that it will allow the Angular app to communicate with the Server.
 
Adding .NET Core Web API project
 
To add .NET Core web API project let's follow the below steps,
 
Angular 7 SPA CRUD With ASP.NET Core And Entity Framework Core 
 
Once we are done with adding the project let’s move towards the Added Project and make the necessary changes
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Threading.Tasks;  
  5. using Angular7DemoServices;  
  6. using Microsoft.AspNetCore.Builder;  
  7. using Microsoft.AspNetCore.Hosting;  
  8. using Microsoft.AspNetCore.Mvc;  
  9. using Microsoft.EntityFrameworkCore;  
  10. using Microsoft.Extensions.Configuration;  
  11. using Microsoft.Extensions.DependencyInjection;  
  12. using Microsoft.Extensions.Logging;  
  13. using Microsoft.Extensions.Options;  
  14.   
  15. namespace Angular6DemoServices  
  16. {  
  17.     public class Startup  
  18.     {  
  19.         public Startup(IConfiguration configuration)  
  20.         {  
  21.             Configuration = configuration;  
  22.         }  
  23.   
  24.         public IConfiguration Configuration { get; }  
  25.   
  26.         // This method gets called by the runtime. Use this method to add services to the container.  
  27.         public void ConfigureServices(IServiceCollection services)  
  28.         {  
  29.             services.AddMvc();  
  30.             services.AddCors();  
  31.             services.AddDbContext<AppDbContext>(opt => opt.UseSqlServer(@"Your connection string"));  
  32.            
  33.         }  
  34.   
  35.         // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.  
  36.         public void Configure(IApplicationBuilder app, IHostingEnvironment env)  
  37.         {  
  38.             if (env.IsDevelopment())  
  39.             {  
  40.                 app.UseDeveloperExceptionPage();  
  41.             }  
  42.             app.UseMiddleware();  
  43.             app.UseCors();  
  44.              
  45.             app.UseMvc();  
  46.         }  
  47.     }  
  48. }  
This is our startup class where we are configuring the services and registering the services
 
In this, the first thing is to Add the Database context where we are using the SQL server as a database
 
The next thing that we need to do is to configure the CORS Option where we allow the Cross origin resource sharing from the Angular application. Apart from that we have added the Middleware which will again helps us in the CORS issue. The middleware code can be like below
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Threading.Tasks;  
  5. using Microsoft.AspNetCore.Builder;  
  6. using Microsoft.AspNetCore.Http;  
  7.   
  8. namespace Angular7DemoServices  
  9. {  
  10.     // You may need to install the Microsoft.AspNetCore.Http.Abstractions package into your project  
  11.     public class CorsMiddleware  
  12.     {  
  13.         private readonly RequestDelegate _next;  
  14.   
  15.         public CorsMiddleware(RequestDelegate next)  
  16.         {  
  17.             _next = next;  
  18.         }  
  19.   
  20.         public Task Invoke(HttpContext httpContext)  
  21.         {  
  22.   
  23.             httpContext.Response.Headers.Add("Access-Control-Allow-Origin""*");  
  24.             httpContext.Response.Headers.Add("Access-Control-Allow-Credentials""true");  
  25.             httpContext.Response.Headers.Add("Access-Control-Allow-Headers""Content-Type, Accept");  
  26.             httpContext.Response.Headers.Add("Access-Control-Allow-Methods""POST,GET,PUT,PATCH,DELETE,OPTIONS");  
  27.             return _next(httpContext);  
  28.         }  
  29.     }  
  30.   
  31.     // Extension method used to add the middleware to the HTTP request pipeline.  
  32.     public static class MiddlewareExtensions  
  33.     {  
  34.         public static IApplicationBuilder UseMiddleware(this IApplicationBuilder builder)  
  35.         {  
  36.             return builder.UseMiddleware<CorsMiddleware>();  
  37.         }  
  38.     }  
  39. }  
This will be the middleware which will add the needed headers in the request and response to and from the API. The Rest part in the Code is nothing but a simple CRUD Operation which we are familiar with, but if not we can find it on the Github which will be shared below.
 
So when we Run the web API and the Angular Application we can see the output as below,
 
Angular 7 SPA CRUD With ASP.NET Core And Entity Framework Core 
 
Future Expansion of this article
 
After seeing the output you might be wondering what these signup and login buttons are doing there, so they are for future articles, and what we would have in that includes:
  1. Login and Signup with the external authentication like Facebook and Gmail and twitter
  2. Using Identity server at the Web api end
  3. Adding new Modules for the employee where they can login and add their daily timesheet
  4. For the Admin Tracking their daily activities

    If anyone is interested you can contribute to this project which is present at the below link.
Source code Link
 
Here is the Source code link for the above article
References
 
https://angular.io/