In this post, I will describe how to create a CRUD application using Angular 4, HTML 5, Web API, C# and SQL Server by extending the VS2017 solution developed in the previous article.
Source Code : The complete source code for the article is available at GitHub repository : https://github.com/sudipta-chaudhari/Angular4_CRUD_WebAPI_EF
Technologies Used : Angular 4, Web API, C#, Entity Framework, SQL Server, HTML 5, Bootstrap
IDE Used : Visual Studio 2017
External Components Used : PrimeNG
Key Learnings :
(1) CRUD Operations on SQL Server database using ASP.NET Web API, LINQ, C#, Entity Framework
(2) Angular 4 Service – DataService, Validation Service
(3) Angular 4 – REST API call
(4) Angular 4 Reactive Forms Validation
(5) Angular 4 Grid component using PrimeNG DataTable
(6) Angular 4 modal popup using PrimeNG Dialog
Application Architecture :
Application Screens :
(1) Display Products (CRUD)
(2) Add Product (CRUD)
(3) Update Product (CRUD)
(4) Delete Product (CRUD)
Let’s proceed to build the application’s code.
Step 1 : Create Database and Table
Create a new SQL Server database and a table named
Product with schema as below.
Database ER Diagram :
Database Table Script :
1
2
3
4
5
6
7
8
9
10
11
12
| CREATE TABLE [dbo].[Product]( [Id] [int] IDENTITY(1,1) NOT NULL, [Name] [varchar](20) NOT NULL, [Category] [varchar](20) NOT NULL, [Price] [decimal](10, 2) NOT NULL, CONSTRAINT [PK_TblProductList] PRIMARY KEY CLUSTERED( [Id] ASC)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]) ON [PRIMARY]GO |
Step 2 : Create ADO.NET Entity Data Model
Under application root path, add a folder named “DBModel” and add an ADO.NET Entity Data Model named
InventoryModel.edmx which looks as shown below.Step 3 : Create ViewModel Class
Under application root path, add a folder named “Models” and add a ViewModel class named
ProductJSON.cs as shown below.
1
2
3
4
5
6
7
8
9
10
| namespace Angular4WebApi.Models{ public class ProductJSON { public int Id { get; set; } public string Name { get; set; } public string Category { get; set; } public decimal Price { get; set; } }} |
Step 4 : Create Web API Controller
Under ‘Controllers’ folder, add a new Web API controller named
ProductController.cs with the code shown below.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
| using Angular4WebApi.DBModel;using Angular4WebApi.Models;using System;using System.Collections.Generic;using System.Linq;using System.Web.Http;namespace Angular4WebApi.Controllers{ public class ProductController : ApiController { private readonly InventoryEntities _context; public ProductController() { _context = new InventoryEntities(); } // GET api/<controller> [Route("api/Product/GetProducts")] public IEnumerable<ProductJSON> GetProducts() { IQueryable<ProductJSON> products = _context.Product.Select( p => new ProductJSON { Id = p.Id, Name = p.Name, Category = p.Category, Price = p.Price }); return products.ToList(); } // POST api/<controller> public Product Post([FromBody]Product product) { if (product == null) { throw new ArgumentNullException("product"); } Product newProduct = new Product(); try { newProduct.Name = product.Name; newProduct.Category = product.Category; newProduct.Price = product.Price; _context.Product.Add(newProduct); int rowsAffected = _context.SaveChanges(); return rowsAffected > 0 ? product : null; } catch (Exception e) { throw e; } } // PUT api/<controller>/5 public bool Put(int id, [FromBody]Product p) { p.Id = id; if (p == null) { throw new ArgumentNullException("p"); } using (var ctx = new InventoryEntities()) { var product = _context.Product.Single(a => a.Id == p.Id); if (product != null) { product.Name = p.Name; product.Category = p.Category; product.Price = p.Price; int rowsAffected = _context.SaveChanges(); return rowsAffected > 0 ? true : false; } else { return false; } } } // DELETE api/<controller>/5 public bool Delete(int id) { using (var ctx = new InventoryEntities()) { Product products = ctx.Product.Find(id); ctx.Product.Remove(products); int rowsAffected = ctx.SaveChanges(); return rowsAffected > 0 ? true : false; } } }} |
The Web API Controller contains the below methods:
IEnumerable GetProducts() – GET API method which returns entire list of products as an IEnumerable type.
This method will be used to bind data to the PrimeNG DataTable grid.
Product Post([FromBody]Product product) – this method accepts a object of type Product which corresponds to the database Product table and returns a Productobject.
This method will be used to add a new product.
public bool Put(int id, [FromBody]Product p) – this method accepts a object of type Product which corresponds to the database Product table from JSON body and a second parameter as the product id and returns a boolean.
This method will be used to update an existing product by ProductId and returns a boolean value to indicate success or failure status of update operation.
public bool Delete(int id) – this method accepts a ProductId returns a boolean.
This method will be used to delete an existing product by ProductId and returns a boolean value to indicate success or failure status of delete operation.
Step 5 : Create Angular4 Data Service
Under application root path’s ‘app’ folder (created as a part of the solution in my previous post), add a folder ‘service’ and create a typescript file dataService.ts’. This will be used to call the Web API REST endpoints using
rxjs package Angular HTTP components.
This service will be Dependency Injected into the typescript component in Step (7).
The complete code for dataService.ts is provided below.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
| import { Injectable } from '@angular/core';import { Http, Response, Headers, RequestOptions } from '@angular/http';import 'rxjs/add/operator/toPromise';import { Product } from '../model/product';import { Observable } from 'rxjs/Observable';import 'rxjs/add/operator/map';@Injectable()export class InventoryService { constructor(private http: Http) {} public getAllProducts() { return this.http.get('/api/Product/GetProducts').map((res: Response) => <Product[]>res.json()) } addProduct(product) { let headers = new Headers({ 'Content-Type': 'application/json' }); let options = new RequestOptions({ headers: headers }); let body = JSON.stringify(product); return this.http.post('/api/Product/', body, options).map((res: Response) => res.json()); } updateProduct(product) { let headers = new Headers({ 'Content-Type': 'application/json' }); let options = new RequestOptions({ headers: headers }); let body = JSON.stringify(product); return this.http.put('/api/Product/' + product.Id, body, options).map((res: Response) => res.json()); } deleteProduct(product) { return this.http.delete('/api/Product/' + product.Id); }} |
Step 6 : Create Angular4 Validation Service
Under folder ‘service’ created in previous step, create a typescript file validationService.ts’. This will be used to validate the Angular HTML view’s textboxes to check empty field, minimum and maximum field length.
This service will be Dependency Injected into the typescript component in Step (7).
The complete code for dataService.ts is provided below.
1
2
3
4
5
6
7
8
9
10
| import {FormControl} from '@angular/forms';export class ValidationService { static nospaceValidator(control: FormControl): { [s: string]: boolean } { let re = / /; if (control.value && control.value.match(re)) { return { nospace: true }; } }} |
The validation service method uses regular expression to check for empty string.



0 comments:
Post a Comment
Note: only a member of this blog may post a comment.