Dylan  Iqbal

Dylan Iqbal

1560822820

Building Web App using ASP.NET Web API Angular 7 and SQL Server

The comprehensive step by step tutorial on building Web Application using ASP.NET Web API, Angular 7 and Microsoft SQL Server. In this tutorial, we will create a RESTful API web service using ASP.NET Core Web API then create a front-end application with Angular 7. For the backend, we use Microsoft SQL Server 2017 Express Edition with the additional database Northwind. This is our first ASP.NET tutorial, so there will be many shortcomings and a lot of discussions.

Table of Contents:

The following tools, frameworks, package, and modules are required for this tutorial:

We assume that you already install all above required tools. Now, we have to check that DotNet SDK already installed and added to the path. Open command prompt then type this command to make sure DotNet installed and runnable via command prompt.

dotnet --version

You will get this result.

2.1.403

We are using DotNet Framework SDK version 2.1.403. That’s mean you’re ready to move to the main steps.

1. Download and Install Northwind Sample Database

To download Northwind sample database for SQL Server 2017, open your browser then go to this link https://northwinddatabase.codeplex.com/. After download, extract to your root folder (for example C:). Next, open Microsoft SQL Server Management Studio. Login to your local Server then right-click Database in the Object Explorer Window then choose Restore Database.

Choose Device then Click … button. The select device dialog will open then click Add button, browse to the .bak file that previously extracted then click OK button then click again OK button.

Click OK button to Restore the Northwind Database. Now, you should see the Northwind Database in the Database.

2. Create and Configure a new ASP.NET Web API Application

A slightly different of ASP.NET Core application creation, we will use the command prompt. Of course, you can use the more easiest way when using Microsoft Visual Studio. In the command prompt go to your projects folder then type this command.

dotnet  new webapi –o AspNetAngular –n AspNetAngular

You will the output like below in the Command Prompt.

The template "ASP.NET Core Web API" was created successfully.

Processing post-creation actions...
Running 'dotnet restore' on AspNetAngular\AspNetAngular.csproj...
  Restoring packages for C:\Users\DIDIN\Projects\AspNetAngular\AspNetAngular.csproj...
  Generating MSBuild file C:\Users\DIDIN\Projects\AspNetAngular\obj\AspNetAngular.csproj.nuget.g.props.
  Generating MSBuild file C:\Users\DIDIN\Projects\AspNetAngular\obj\AspNetAngular.csproj.nuget.g.targets.
  Restore completed in 5.82 sec for C:\Users\DIDIN\Projects\AspNetAngular\AspNetAngular.csproj.

Restore succeeded.

That’s mean, you can open directly as a folder from Visual Studio Code as well as CSharp Project/Solution from Microsoft Visual Studio. Or you can call this new ASP.NET Core Web API Project by type this command.

cd AspNetAngular
code .

The project will be opened by Visual Studio Code. If you get a notification like below just click Yes button.

Next, open terminal from the menu or press Ctrl+Shift+`. Run these commands to installs all required packages

dotnet add package Microsoft.EntityFrameworkCore.Tools -v 2.1.2
dotnet add package Microsoft.EntityFrameworkCore.SqlServer -v 2.1.2
dotnet add package Microsoft.EntityFrameworkCore.SqlServer.Design -v 1.1.6
dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design -v 2.1.5
dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Tools -v 2.0.4
dotnet add package AutoMapper.Extensions.Microsoft.DependencyInjection -v 5.0.1

If you see a notification like below, just click Restore button.

Now, you will have this packages with the right version installed shown in AspNetAngular.csproj file.

<ItemGroup>
&nbsp; <PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="6.0.0" />
&nbsp; <PackageReference Include="Microsoft.AspNetCore.App" />
&nbsp; <PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.1.2" PrivateAssets="All" />
&nbsp; <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="2.1.2" />
&nbsp; <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer.Design" Version="1.1.6" />
&nbsp; <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="2.1.2">
&nbsp; &nbsp; <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
&nbsp; &nbsp; <PrivateAssets>all</PrivateAssets>
&nbsp; </PackageReference>
&nbsp; <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.1.5" />
&nbsp; <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.4" />
</ItemGroup>

Next, build the DotNet application to make sure there’s no error in package dependencies.

dotnet build

You must see this output when everything on the right path.

Build succeeded.
&nbsp; &nbsp; 0 Warning(s)
&nbsp; &nbsp; 0 Error(s)

Next, we have to configure connections to Microsoft SQL Server Database. First, open and edit appsettings.json then add this lines before logging JSON object.

"ConnectionStrings": {
&nbsp; "SQLConnection": "Server=.;Database=NORTHWND;Trusted_Connection=True;User Id=sa;Password=q;Integrated Security=false;MultipleActiveResultSets=true"
},

Open and edit Startup.cs then add this line inside ConfigureServices bracket.

services.AddDbContext<NORTHWNDContext>(options => options.UseSqlServer(Configuration.GetConnectionString("SQLConnection")));

Next, add this line to enable CORS after above line.

services.AddCors();

Also, add this line inside Configure bracket.

app.UseCors(x => x.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod());

Don’t forget to import the library or module that added in the Configuration.

3. Generate Models from Microsoft SQL Server Database

We will use the Code Generation Tools package to generate all models that represent all tables in the Northwind Database. Run this command to generate the models and their context.

dotnet ef dbcontext scaffold "Server=.;Database=NORTHWND;Trusted_Connection=True;User Id=sa;Password=q;Integrated Security=false;" Microsoft.EntityFrameworkCore.SqlServer -o Models

You will see the generated Models and Context inside the Models folder.

If there’s a lot of warning or error that comes from IDE linter, just re-open the Visual Studio Code. As you see in the table of contents, we will use only Supplier model for this tutorial. The generated suppliers look like this.

using System;
using System.Collections.Generic;

namespace AspNetAngular.Models
{
&nbsp; &nbsp; public partial class Suppliers
&nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; public Suppliers()
&nbsp; &nbsp; &nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Products = new HashSet<Products>();
&nbsp; &nbsp; &nbsp; &nbsp; }

&nbsp; &nbsp; &nbsp; &nbsp; public int SupplierId { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string CompanyName { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string ContactName { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string ContactTitle { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string Address { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string City { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string Region { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string PostalCode { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string Country { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string Phone { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string Fax { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string HomePage { get; set; }

&nbsp; &nbsp; &nbsp; &nbsp; public ICollection<Products> Products { get; set; }
&nbsp; &nbsp; }
}

That model declared in the NORTHWNDContext.cs the file inside Models folder.

public virtual DbSet<Suppliers> Suppliers { get; set; }

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
&nbsp; modelBuilder.Entity<Suppliers>(entity =>
&nbsp; {
&nbsp; &nbsp; &nbsp; entity.HasKey(e => e.SupplierId);

&nbsp; &nbsp; &nbsp; entity.HasIndex(e => e.CompanyName)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .HasName("CompanyName");

&nbsp; &nbsp; &nbsp; entity.HasIndex(e => e.PostalCode)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .HasName("PostalCode");

&nbsp; &nbsp; &nbsp; entity.Property(e => e.SupplierId).HasColumnName("SupplierID");

&nbsp; &nbsp; &nbsp; entity.Property(e => e.Address).HasMaxLength(60);

&nbsp; &nbsp; &nbsp; entity.Property(e => e.City).HasMaxLength(15);

&nbsp; &nbsp; &nbsp; entity.Property(e => e.CompanyName)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .IsRequired()
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .HasMaxLength(40);

&nbsp; &nbsp; &nbsp; entity.Property(e => e.ContactName).HasMaxLength(30);

&nbsp; &nbsp; &nbsp; entity.Property(e => e.ContactTitle).HasMaxLength(30);

&nbsp; &nbsp; &nbsp; entity.Property(e => e.Country).HasMaxLength(15);

&nbsp; &nbsp; &nbsp; entity.Property(e => e.Fax).HasMaxLength(24);

&nbsp; &nbsp; &nbsp; entity.Property(e => e.HomePage).HasColumnType("ntext");

&nbsp; &nbsp; &nbsp; entity.Property(e => e.Phone).HasMaxLength(24);

&nbsp; &nbsp; &nbsp; entity.Property(e => e.PostalCode).HasMaxLength(10);

&nbsp; &nbsp; &nbsp; entity.Property(e => e.Region).HasMaxLength(15);
&nbsp; });
}

4. Create DTO (Data Transfer Object) for Request Body and Response

To specify request body and response fields, we will use a Data Transfer Object (DTO). For that, create a new DTOs folder and AddSupplierDto.cs, EditSupplierDto.cs, SupplierResponse.cs files inside that folder. Next, open and edit AddSupplierDto.cs then Replace all codes with this.

using System;
using System.ComponentModel.DataAnnotations;

namespace AspNetAngular.Dtos
{
&nbsp; &nbsp; public class AddSupplierDto
&nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; [Required]
&nbsp; &nbsp; &nbsp; &nbsp; public string CompanyName { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string ContactName { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string ContactTitle { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string Address { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string City { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string Region { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string PostalCode { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string Country { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string Phone { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string Fax { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string HomePage { get; set; }
&nbsp; &nbsp; }
}

Next, open and edit EditSupplierDto.cs then Replace all codes with this.

using System;
using System.ComponentModel.DataAnnotations;

namespace AspNetAngular.Dtos
{
&nbsp; &nbsp; public class EditSupplierDto
&nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; [Required]
&nbsp; &nbsp; &nbsp; &nbsp; public int SupplierId { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; [Required]
&nbsp; &nbsp; &nbsp; &nbsp; public string CompanyName { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string ContactName { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string ContactTitle { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string Address { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string City { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string Region { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string PostalCode { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string Country { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string Phone { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string Fax { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string HomePage { get; set; }
&nbsp; &nbsp; }
}

Next, open and edit SupplierResponseDto.cs then Replace all codes with this.

namespace AspNetAngular.Dtos
{
&nbsp; &nbsp; public class SupplierResponseDto
&nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; public int SupplierId { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string CompanyName { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string ContactName { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string ContactTitle { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string Address { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string City { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string PostalCode { get; set; }

&nbsp; &nbsp; }
}

5. Create Helpers Class for Mapping DTO with Model Classes

To create a helper for mapping DTO to Model classes, create the folder Helpers in the root of project folder then create a file AutoMapperProfile.cs inside that new folder. Open and edit this new file then replace all codes with this.

using AspNetAngular.Dtos;
using AspNetAngular.Models;
using AutoMapper;

namespace AspNetAngular.Helpers
{
&nbsp; &nbsp; public class AutoMapperProfiles: Profile
&nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; public AutoMapperProfiles()
&nbsp; &nbsp; &nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CreateMap<AddSupplierDto, Suppliers>();
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CreateMap<EditSupplierDto, Suppliers>();
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CreateMap<Suppliers, SupplierResponseDto>();
&nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; }
}

Next, open and edit again Startup.cs then add this line inside ConfigureServices.

services.AddAutoMapper();

Don’t forget to auto import the library in ConfigureServices.

6. Create Repositories for CRUD (Create, Read, Update Delete) Operations

To create a repository class and interface, we have to create a folder Repositories in the root of the project folder. Next, create an interface file inside that folder with the name IDataRepository.cs then replace all codes with this.

using System.Threading.Tasks;

namespace AspNetAngular.Repositories
{
&nbsp; &nbsp; public interface IDataRepository<T> where T : class
&nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; void Add(T entity);
&nbsp; &nbsp; &nbsp; &nbsp; void Update(T entity);
&nbsp; &nbsp; &nbsp; &nbsp; void Delete(T entity);
&nbsp; &nbsp; &nbsp; &nbsp; Task<T> SaveAsync(T entity);
&nbsp; &nbsp; }
}

Next, create a file inside that folder with the name DataRepository.cs then replace all codes with this.

using System.Threading.Tasks;
using AspNetAngular.Models;

namespace AspNetAngular.Repositories
{
&nbsp; &nbsp; public class DataRepository<T> : IDataRepository<T> where T : class
&nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; private readonly NORTHWNDContext _context;

&nbsp; &nbsp; &nbsp; &nbsp; public DataRepository(NORTHWNDContext context)
&nbsp; &nbsp; &nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _context = context;
&nbsp; &nbsp; &nbsp; &nbsp; }

&nbsp; &nbsp; &nbsp; &nbsp; public void Add(T entity)
&nbsp; &nbsp; &nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _context.Set<T>().Add(entity);
&nbsp; &nbsp; &nbsp; &nbsp; }

&nbsp; &nbsp; &nbsp; &nbsp; public void Update(T entity)
&nbsp; &nbsp; &nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _context.Set<T>().Update(entity);
&nbsp; &nbsp; &nbsp; &nbsp; }

&nbsp; &nbsp; &nbsp; &nbsp; public void Delete(T entity)
&nbsp; &nbsp; &nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _context.Set<T>().Remove(entity);
&nbsp; &nbsp; &nbsp; &nbsp; }

&nbsp; &nbsp; &nbsp; &nbsp; public async Task<T> SaveAsync(T entity)
&nbsp; &nbsp; &nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; await _context.SaveChangesAsync();
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return entity;
&nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; }
}

Next, open and edit again Startup.cs then add this line inside ConfigureServices bracket.

services.AddScoped(typeof(IDataRepository < > ), typeof(DataRepository < > ));

Also, import the required classes and libraries.

7. Create Controller for CRUD Operations

Now, we will show you how the API available via Controller. We will generate a controller for Supplier model. Before generate, we have to install the tools for it. Run this command in the terminal of Visual Studio Code.

dotnet tool install --global dotnet-aspnet-codegenerator --version 2.2.1

Just run this command to generate it.

dotnet aspnet-codegenerator controller -name SupplierController -api -async -m AspNetAngular.Models.Suppliers -dc NORTHWNDContext -namespace AspNetAngular.Controllers -outDir Controllers

Now, we have a Supplier’s controller that looks like this.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using AspNetAngular.Models;

namespace AspNetAngular.Controllers
{
&nbsp; &nbsp; [Route("api/[controller]")]
&nbsp; &nbsp; [ApiController]
&nbsp; &nbsp; public class SupplierController : ControllerBase
&nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; private readonly NORTHWNDContext _context;

&nbsp; &nbsp; &nbsp; &nbsp; public SupplierController(NORTHWNDContext context)
&nbsp; &nbsp; &nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _context = context;
&nbsp; &nbsp; &nbsp; &nbsp; }

&nbsp; &nbsp; &nbsp; &nbsp; // GET: api/Supplier
&nbsp; &nbsp; &nbsp; &nbsp; [HttpGet]
&nbsp; &nbsp; &nbsp; &nbsp; public IEnumerable<Suppliers> GetSuppliers()
&nbsp; &nbsp; &nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return _context.Suppliers;
&nbsp; &nbsp; &nbsp; &nbsp; }

&nbsp; &nbsp; &nbsp; &nbsp; // GET: api/Supplier/5
&nbsp; &nbsp; &nbsp; &nbsp; [HttpGet("{id}")]
&nbsp; &nbsp; &nbsp; &nbsp; public async Task<IActionResult> GetSuppliers([FromRoute] int id)
&nbsp; &nbsp; &nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (!ModelState.IsValid)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return BadRequest(ModelState);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var suppliers = await _context.Suppliers.FindAsync(id);

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (suppliers == null)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return NotFound();
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return Ok(suppliers);
&nbsp; &nbsp; &nbsp; &nbsp; }

&nbsp; &nbsp; &nbsp; &nbsp; // PUT: api/Supplier/5
&nbsp; &nbsp; &nbsp; &nbsp; [HttpPut("{id}")]
&nbsp; &nbsp; &nbsp; &nbsp; public async Task<IActionResult> PutSuppliers([FromRoute] int id, [FromBody] Suppliers suppliers)
&nbsp; &nbsp; &nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (!ModelState.IsValid)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return BadRequest(ModelState);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (id != suppliers.SupplierId)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return BadRequest();
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _context.Entry(suppliers).State = EntityState.Modified;

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; try
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; await _context.SaveChangesAsync();
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; catch (DbUpdateConcurrencyException)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (!SuppliersExists(id))
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return NotFound();
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; else
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return NoContent();
&nbsp; &nbsp; &nbsp; &nbsp; }

&nbsp; &nbsp; &nbsp; &nbsp; // POST: api/Supplier
&nbsp; &nbsp; &nbsp; &nbsp; [HttpPost]
&nbsp; &nbsp; &nbsp; &nbsp; public async Task<IActionResult> PostSuppliers([FromBody] Suppliers suppliers)
&nbsp; &nbsp; &nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (!ModelState.IsValid)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return BadRequest(ModelState);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _context.Suppliers.Add(suppliers);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; await _context.SaveChangesAsync();

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return CreatedAtAction("GetSuppliers", new { id = suppliers.SupplierId }, suppliers);
&nbsp; &nbsp; &nbsp; &nbsp; }

&nbsp; &nbsp; &nbsp; &nbsp; // DELETE: api/Supplier/5
&nbsp; &nbsp; &nbsp; &nbsp; [HttpDelete("{id}")]
&nbsp; &nbsp; &nbsp; &nbsp; public async Task<IActionResult> DeleteSuppliers([FromRoute] int id)
&nbsp; &nbsp; &nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (!ModelState.IsValid)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return BadRequest(ModelState);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var suppliers = await _context.Suppliers.FindAsync(id);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (suppliers == null)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return NotFound();
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _context.Suppliers.Remove(suppliers);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; await _context.SaveChangesAsync();

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return Ok(suppliers);
&nbsp; &nbsp; &nbsp; &nbsp; }

&nbsp; &nbsp; &nbsp; &nbsp; private bool SuppliersExists(int id)
&nbsp; &nbsp; &nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return _context.Suppliers.Any(e => e.SupplierId == id);
&nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; }
}

As you see that generated Controllers using original fields from the Suppliers Model. Next, we will use our previous created DTO for custom Object save, edit and their response. Open and edit Controllers/SupplierController.cs then add this variable after context variable.

private readonly IMapper _mapper;
private readonly IDataRepository<Suppliers> _repo;

Also, inject to the SupplierController constructor.

public SupplierController(NORTHWNDContext context, IMapper mapper, IDataRepository<Suppliers> repo)
{
&nbsp; &nbsp; _context = context;
&nbsp; &nbsp; _mapper = mapper;
&nbsp; &nbsp; _repo = repo;
}

Don’t forget to import all required libraries or classes. Next, replace the HTTPPost method with this codes.

// POST: api/Supplier
[HttpPost]
public async Task<IActionResult> PostSuppliers([FromBody] AddSupplierDto addSupplierDto)
{
&nbsp; &nbsp; if (!ModelState.IsValid)
&nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; return BadRequest(ModelState);
&nbsp; &nbsp; }

&nbsp; &nbsp; var preSupplier = _mapper.Map<Suppliers>(addSupplierDto);
&nbsp; &nbsp; _repo.Add(preSupplier);
&nbsp; &nbsp; var saveSupplier = await _repo.SaveAsync(preSupplier);
&nbsp; &nbsp; var supplierResponse = _mapper.Map<SupplierResponseDto>(saveSupplier);

&nbsp; &nbsp; return StatusCode(201, new { supplierResponse });
}

Next, replace the HTTPPut method with this codes.

// PUT: api/Supplier/5
[HttpPut("{id}")]
public async Task<IActionResult> PutSuppliers([FromRoute] int id, [FromBody] EditSupplierDto editSupplierDto)
{
&nbsp; &nbsp; if (!ModelState.IsValid)
&nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; return BadRequest(ModelState);
&nbsp; &nbsp; }

&nbsp; &nbsp; if (id != editSupplierDto.SupplierId)
&nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; return BadRequest();
&nbsp; &nbsp; }

&nbsp; &nbsp; var preSupplier = _mapper.Map<Suppliers>(editSupplierDto);
&nbsp; &nbsp; _repo.Update(preSupplier);
&nbsp; &nbsp; await _repo.SaveAsync(preSupplier);

&nbsp; &nbsp; return NoContent();
}

Finally, replace the HTTPDelete method with this because we will delete manually busing SQL Query the related table.

// DELETE: api/Supplier/5
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteSuppliers([FromRoute] int id)
{
&nbsp; &nbsp; if (!ModelState.IsValid)
&nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; return BadRequest(ModelState);
&nbsp; &nbsp; }

&nbsp; &nbsp; var suppliers = await _context.Suppliers.FindAsync(id);

&nbsp; &nbsp; if (suppliers == null)
&nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; return NotFound();
&nbsp; &nbsp; }

&nbsp; &nbsp; _context.Database.ExecuteSqlCommand("DELETE FROM [Order Details] WHERE ProductID IN (SELECT ProductID FROM Products WHERE SupplierID = @supplierId)",
&nbsp; &nbsp; &nbsp; &nbsp; new SqlParameter("@supplierId", suppliers.SupplierId));

&nbsp; &nbsp; _context.Database.ExecuteSqlCommand("DELETE FROM Products WHERE SupplierID = @supplierId",
&nbsp; &nbsp; &nbsp; &nbsp; new SqlParameter("@supplierId", suppliers.SupplierId));

&nbsp; &nbsp; _context.Suppliers.Remove(suppliers);
&nbsp; &nbsp; await _context.SaveChangesAsync();

&nbsp; &nbsp; return Ok(suppliers);
}

8. Test API using Postman

Now, we have to run the ASP.NET Core Web API from the Terminal by typing this command.

dotnet watch run

Watch keyword is the additional command for monitoring any change in the codes then reloading the ASP.NET Core Web API application. Next, open or run the Postman application. Use the GET method and fill the right column after the GET method with localhost:5000/api/Supplier, Headers key with Content-Type, Headers value with application/json.

Now, click the Send button and you should see this result for successful GET Supplier.

[
&nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; "supplierId": 1,
&nbsp; &nbsp; &nbsp; &nbsp; "companyName": "Exotic Liquids",
&nbsp; &nbsp; &nbsp; &nbsp; "contactName": "Charlotte Cooper",
&nbsp; &nbsp; &nbsp; &nbsp; "contactTitle": "Purchasing Manager",
&nbsp; &nbsp; &nbsp; &nbsp; "address": "49 Gilbert St.",
&nbsp; &nbsp; &nbsp; &nbsp; "city": "London",
&nbsp; &nbsp; &nbsp; &nbsp; "region": null,
&nbsp; &nbsp; &nbsp; &nbsp; "postalCode": "EC1 4SD",
&nbsp; &nbsp; &nbsp; &nbsp; "country": "UK",
&nbsp; &nbsp; &nbsp; &nbsp; "phone": "(171) 555-2222",
&nbsp; &nbsp; &nbsp; &nbsp; "fax": null,
&nbsp; &nbsp; &nbsp; &nbsp; "homePage": null,
&nbsp; &nbsp; &nbsp; &nbsp; "products": []
&nbsp; &nbsp; },
&nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; "supplierId": 2,
&nbsp; &nbsp; &nbsp; &nbsp; "companyName": "New Orleans Cajun Delights",
&nbsp; &nbsp; &nbsp; &nbsp; "contactName": "Shelley Burke",
&nbsp; &nbsp; &nbsp; &nbsp; "contactTitle": "Order Administrator",
&nbsp; &nbsp; &nbsp; &nbsp; "address": "P.O. Box 78934",
&nbsp; &nbsp; &nbsp; &nbsp; "city": "New Orleans",
&nbsp; &nbsp; &nbsp; &nbsp; "region": "LA",
&nbsp; &nbsp; &nbsp; &nbsp; "postalCode": "70117",
&nbsp; &nbsp; &nbsp; &nbsp; "country": "USA",
&nbsp; &nbsp; &nbsp; &nbsp; "phone": "(100) 555-4822",
&nbsp; &nbsp; &nbsp; &nbsp; "fax": null,
&nbsp; &nbsp; &nbsp; &nbsp; "homePage": "#CAJUN.HTM#",
&nbsp; &nbsp; &nbsp; &nbsp; "products": []
&nbsp; &nbsp; },
&nbsp; &nbsp; ...
]

To get single supplier by supplier ID, just change the URL to this localhost:5000/api/Supplier/2. If found, you will see the result of a single supplier. Next, for POST a Supplier changes the method to POST, leave URL same as the GET supplier list then fill the body with a raw JSON object.

{
&nbsp; "CompanyName": "Djamware Inc.",
&nbsp; "ContactName": "Didin J.",
&nbsp; "ContactTitle": "CEO",
&nbsp; "Address": "Whereever Road 123",
&nbsp; "City": "Bandung",
&nbsp; "Region": "JBR",
&nbsp; "PostalCode": "12345",
&nbsp; "Country": "Indonesia",
&nbsp; "Phone": "(022) 123-4567890",
&nbsp; "Fax": "(022) 123-4567890",
&nbsp; "HomePage": "https://www.djamware.com"
}

You will see this result with status 201.

{
&nbsp; &nbsp; "supplierResponse": {
&nbsp; &nbsp; &nbsp; &nbsp; "companyName": "Djamware Inc.",
&nbsp; &nbsp; &nbsp; &nbsp; "contactName": "Didin J.",
&nbsp; &nbsp; &nbsp; &nbsp; "contactTitle": "CEO",
&nbsp; &nbsp; &nbsp; &nbsp; "address": "Whereever Road 123",
&nbsp; &nbsp; &nbsp; &nbsp; "city": "Bandung",
&nbsp; &nbsp; &nbsp; &nbsp; "region": "JBR",
&nbsp; &nbsp; &nbsp; &nbsp; "postalCode": "12345",
&nbsp; &nbsp; &nbsp; &nbsp; "country": "Indonesia",
&nbsp; &nbsp; &nbsp; &nbsp; "phone": "(022) 123-4567890",
&nbsp; &nbsp; &nbsp; &nbsp; "fax": "(022) 123-4567890",
&nbsp; &nbsp; &nbsp; &nbsp; "homePage": "https://www.djamware.com"
&nbsp; &nbsp; }
}

To update the Supplier data, change the method to PUT and URL to localhost:5000/api/Supplier/30 then add a supplier id field to the raw body.

{
&nbsp; "SupplierId": 30,
&nbsp; "CompanyName": "Djamware.com",
&nbsp; "ContactName": "Didin J.",
&nbsp; "ContactTitle": "Engineer",
&nbsp; "Address": "Whereever Road 123",
&nbsp; "City": "Garut",
&nbsp; "Region": "JBR",
&nbsp; "PostalCode": "12345",
&nbsp; "Country": "Indonesia",
&nbsp; "Phone": "(022) 123-4567890",
&nbsp; "Fax": "(022) 123-4567890",
&nbsp; "HomePage": "https://www.djamware.com"
}

The response should be 204 (No Content) for a successful request. Next, for delete a supplier, simply change the method to DELETE, keep the URL as the previous method and change the body to none. You should see the 200 response and data that deleted in the response body.

9. Install or Update Angular 7 CLI and Create Application

Before installing the Angular 7 CLI, make sure you have installed Node.js https://nodejs.org and can open Node.js command prompt. Next, open the Node.js command prompt then type this command to install Angular 7 CLI.

npm install -g @angular/cli

Next, create an Angular 7 application by typing this command in the root of ASP.NET Core application/project directory.

ng new client

Where client is the name of the Angular 7 application. You can specify your own name, we like to name it client because it’s put inside ASP.NET Core Project directory. If there’s a question, we fill them with Y and SASS. Next, go to the newly created Angular 7 application.

cd client

Run the Angular 7 application for the first time.

ng serve

Now, go to localhost:4200 and you should see this page.

To stop the Angular 7 application, just press CTRL+C keys.

10. Add Routes for Navigation between Angular 7 Pages/Component

On the previous steps, we have to added Angular 7 Routes when answering the questions. Now, we just added the required pages for CRUD (Create, Read, Update, Delete) Supplier data. Type this commands to add the Angular 7 components or pages.

ng g component supplier
ng g component supplier-detail
ng g component supplier-add
ng g component supplier-edit

Open src/app/app.module.ts then you will see those components imported and declared in @NgModule declarations. Next, open and edit src/app/app-routing.module.ts then add this imports.

import { SupplierComponent } from './supplier/supplier.component';
import { SupplierDetailComponent } from './supplier-detail/supplier-detail.component';
import { SupplierAddComponent } from './supplier-add/supplier-add.component';
import { SupplierEditComponent } from './supplier-edit/supplier-edit.component';

Add these arrays to the existing routes constant.

const routes: Routes = [
&nbsp; {
&nbsp; &nbsp; path: 'supplier',
&nbsp; &nbsp; component: SupplierComponent,
&nbsp; &nbsp; data: { title: 'List of Suppliers' }
&nbsp; },
&nbsp; {
&nbsp; &nbsp; path: 'supplier-details/:id',
&nbsp; &nbsp; component: SupplierDetailComponent,
&nbsp; &nbsp; data: { title: 'Supplier Details' }
&nbsp; },
&nbsp; {
&nbsp; &nbsp; path: 'supplier-add',
&nbsp; &nbsp; component: SupplierAddComponent,
&nbsp; &nbsp; data: { title: 'Add Supplier' }
&nbsp; },
&nbsp; {
&nbsp; &nbsp; path: 'supplier-edit/:id',
&nbsp; &nbsp; component: SupplierEditComponent,
&nbsp; &nbsp; data: { title: 'Edit Supplier' }
&nbsp; },
&nbsp; { path: '',
&nbsp; &nbsp; redirectTo: '/supplier',
&nbsp; &nbsp; pathMatch: 'full'
&nbsp; }
];

Open and edit src/app/app.component.html and you will see existing router outlet. Next, modify this HTML page to fit the CRUD page.

<div style="text-align:center">
&nbsp; <h1>
&nbsp; &nbsp; Welcome to {{ title }}!
&nbsp; </h1>
&nbsp; <img width="300" alt="Angular Logo" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTAgMjUwIj4KICAgIDxwYXRoIGZpbGw9IiNERDAwMzEiIGQ9Ik0xMjUgMzBMMzEuOSA2My4ybDE0LjIgMTIzLjFMMTI1IDIzMGw3OC45LTQzLjcgMTQuMi0xMjMuMXoiIC8+CiAgICA8cGF0aCBmaWxsPSIjQzMwMDJGIiBkPSJNMTI1IDMwdjIyLjItLjFWMjMwbDc4LjktNDMuNyAxNC4yLTEyMy4xTDEyNSAzMHoiIC8+CiAgICA8cGF0aCAgZmlsbD0iI0ZGRkZGRiIgZD0iTTEyNSA1Mi4xTDY2LjggMTgyLjZoMjEuN2wxMS43LTI5LjJoNDkuNGwxMS43IDI5LjJIMTgzTDEyNSA1Mi4xem0xNyA4My4zaC0zNGwxNy00MC45IDE3IDQwLjl6IiAvPgogIDwvc3ZnPg==">
</div>

<div class="container">
&nbsp; <router-outlet></router-outlet>
</div>

Open and edit src/app/app.component.scss then replace all SCSS codes with this.

.container {
&nbsp; padding: 20px;
}

11. Create Service for Accessing RESTful API

To access ASP.NET Core Web API from Angular 7 application, we have to create an Angular 7 Service first. Type this command to create it.

ng g service api

We have to register the HttpClient module before using it in the Service. Open and edit src/app/app.module.ts then add this import.

import { FormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';

Add them to the `@NgModule` imports array.

imports: [
&nbsp; BrowserModule,
&nbsp; FormsModule,
&nbsp; HttpClientModule,
&nbsp; AppRoutingModule
],

To specify the type of response object from the ASP.NET Core Web API, we have to create a class for it. Create a new file src/app/supplier.ts then add this codes.

export class Supplier {
&nbsp; &nbsp; supplierId: number;
&nbsp; &nbsp; companyName: string;
&nbsp; &nbsp; contactName: string;
&nbsp; &nbsp; contactTitle: string;
&nbsp; &nbsp; address: string;
&nbsp; &nbsp; city: string;
&nbsp; &nbsp; region: string;
&nbsp; &nbsp; postalCode: string;
&nbsp; &nbsp; country: string;
&nbsp; &nbsp; phone: string;
&nbsp; &nbsp; fax: string;
&nbsp; &nbsp; homePage: string;
}

Next, open and edit src/app/api.service.ts then add this imports.

import { Observable, of, throwError } from 'rxjs';
import { HttpClient, HttpHeaders, HttpErrorResponse } from '@angular/common/http';
import { catchError, tap, map } from 'rxjs/operators';
import { Supplier } from './supplier';

Add these constants before the @Injectable.

const httpOptions = {
&nbsp; headers: new HttpHeaders({'Content-Type': 'application/json'})
};
const apiUrl = 'http://localhost:5000/api/';

Inject HttpClient module to the constructor.

constructor(private http: HttpClient) { }

Add the error handler function.

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

&nbsp; &nbsp; // TODO: send the error to remote logging infrastructure
&nbsp; &nbsp; console.error(error); // log to console instead

&nbsp; &nbsp; // Let the app keep running by returning an empty result.
&nbsp; &nbsp; return of(result as T);
&nbsp; };
}

Add all CRUD (create, read, update, delete) functions of suppliers data.

getSuppliers (): Observable<Supplier[]> {
&nbsp; return this.http.get<Supplier[]>(apiUrl)
&nbsp; &nbsp; .pipe(
&nbsp; &nbsp; &nbsp; tap(heroes => console.log('fetched Suppliers')),
&nbsp; &nbsp; &nbsp; catchError(this.handleError('getSuppliers', []))
&nbsp; &nbsp; );
}

getSupplier(id: number): Observable<Supplier> {
&nbsp; const url = `${apiUrl}/${id}`;
&nbsp; return this.http.get<Supplier>(url).pipe(
&nbsp; &nbsp; tap(_ => console.log(`fetched Supplier id=${id}`)),
&nbsp; &nbsp; catchError(this.handleError<Supplier>(`getSupplier id=${id}`))
&nbsp; );
}

addSupplier (supplier: any): Observable<Supplier> {
&nbsp; return this.http.post<Supplier>(apiUrl, supplier, httpOptions).pipe(
&nbsp; &nbsp; tap((supplierRes: Supplier) => console.log(`added Supplier w/ id=${supplierRes.supplierId}`)),
&nbsp; &nbsp; catchError(this.handleError<Supplier>('addSupplier'))
&nbsp; );
}

updateSupplier (id: number, supplier: any): Observable<any> {
&nbsp; const url = `${apiUrl}/${id}`;
&nbsp; return this.http.put(url, supplier, httpOptions).pipe(
&nbsp; &nbsp; tap(_ => console.log(`updated Supplier id=${id}`)),
&nbsp; &nbsp; catchError(this.handleError<any>('updateSupplier'))
&nbsp; );
}

deleteSupplier (id: number): Observable<Supplier> {
&nbsp; const url = `${apiUrl}/${id}`;
&nbsp; return this.http.delete<Supplier>(url, httpOptions).pipe(
&nbsp; &nbsp; tap(_ => console.log(`deleted Supplier id=${id}`)),
&nbsp; &nbsp; catchError(this.handleError<Supplier>('deleteSupplier'))
&nbsp; );
}

12. Display List of Suppliers using Angular 7 Material

To display a list of suppliers to the Angular 7 template. First, open and edit src/app/supplier/supplier.component.ts then add this imports.

import { ApiService } from '../api.service';

Next, inject the API Service to the constructor.

constructor(private api: ApiService) { }

Next, for user interface (UI) we will use Angular 7 Material and CDK. There’s a CLI for generating a Material component like Table as a component, but we will create or add the Table component from scratch to existing component. Type this command to install Angular 7 Material.

ng add @angular/material

If there are some questions, answer them like below.

? Choose a prebuilt theme name, or "custom" for a custom theme: Purple/Green &nbsp; &nbsp; &nbsp; [ Preview: https://material.angular.i
o?theme=purple-green ]
? Set up HammerJS for gesture recognition? Yes
? Set up browser animations for Angular Material? Yes

Next, we have to register all required Angular Material components or modules to src/app/app.module.ts. Open and edit that file then add this imports.

import {
&nbsp; MatInputModule,
&nbsp; MatPaginatorModule,
&nbsp; MatProgressSpinnerModule,
&nbsp; MatSortModule,
&nbsp; MatTableModule,
&nbsp; MatIconModule,
&nbsp; MatButtonModule,
&nbsp; MatCardModule,
&nbsp; MatFormFieldModule } from '@angular/material';

Also, modify FormsModule import to add ReactiveFormsModule.

import { FormsModule, ReactiveFormsModule } from '@angular/forms';

Register the above modules to @NgModule imports.

imports: [
&nbsp; BrowserModule,
&nbsp; FormsModule,
&nbsp; HttpClientModule,
&nbsp; AppRoutingModule,
&nbsp; ReactiveFormsModule,
&nbsp; BrowserAnimationsModule,
&nbsp; MatInputModule,
&nbsp; MatTableModule,
&nbsp; MatPaginatorModule,
&nbsp; MatSortModule,
&nbsp; MatProgressSpinnerModule,
&nbsp; MatIconModule,
&nbsp; MatButtonModule,
&nbsp; MatCardModule,
&nbsp; MatFormFieldModule
],

Next, back to src/app/supplier/supplier.component.ts then add this imports.

import { Supplier } from '../supplier';

Declare the variables of Angular Material Table Data Source before the constructor.

displayedColumns: string[] = ['supplierId', 'companyName', 'contactName'];
data: Supplier[] = [];
isLoadingResults = true;

Modify the ngOnInit function to get list of suppliers immediately.

ngOnInit() {
&nbsp; this.api.getSuppliers()
&nbsp; .subscribe(res => {
&nbsp; &nbsp; this.data = res;
&nbsp; &nbsp; console.log(this.data);
&nbsp; &nbsp; this.isLoadingResults = false;
&nbsp; }, err => {
&nbsp; &nbsp; console.log(err);
&nbsp; &nbsp; this.isLoadingResults = false;
&nbsp; });
}

Next, open and edit src/app/supplier/supplier.component.html then replace all HTML tags with this Angular 7 Material tags.

<div class="example-container mat-elevation-z8">
&nbsp; <div class="example-loading-shade"
&nbsp; &nbsp; &nbsp; &nbsp;*ngIf="isLoadingResults">
&nbsp; &nbsp; <mat-spinner *ngIf="isLoadingResults"></mat-spinner>
&nbsp; </div>
&nbsp; <div class="button-row">
&nbsp; &nbsp; <a mat-flat-button color="primary" [routerLink]="['/supplier-add']"><mat-icon>add</mat-icon></a>
&nbsp; </div>
&nbsp; <div class="mat-elevation-z8">
&nbsp; &nbsp; <table mat-table [dataSource]="data" class="example-table"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;matSort matSortActive="CompanyName" matSortDisableClear matSortDirection="asc">

&nbsp; &nbsp; &nbsp; <!-- Supplier ID Column -->
&nbsp; &nbsp; &nbsp; <ng-container matColumnDef="supplierId">
&nbsp; &nbsp; &nbsp; &nbsp; <th mat-header-cell *matHeaderCellDef>Supplier ID</th>
&nbsp; &nbsp; &nbsp; &nbsp; <td mat-cell *matCellDef="let row">{{row.supplierId}}</td>
&nbsp; &nbsp; &nbsp; </ng-container>

&nbsp; &nbsp; &nbsp; <!-- Company Name Column -->
&nbsp; &nbsp; &nbsp; <ng-container matColumnDef="companyName">
&nbsp; &nbsp; &nbsp; &nbsp; <th mat-header-cell *matHeaderCellDef>Company Name</th>
&nbsp; &nbsp; &nbsp; &nbsp; <td mat-cell *matCellDef="let row">{{row.companyName}}</td>
&nbsp; &nbsp; &nbsp; </ng-container>

&nbsp; &nbsp; &nbsp; <!-- Contact Name Column -->
&nbsp; &nbsp; &nbsp; <ng-container matColumnDef="contactName">
&nbsp; &nbsp; &nbsp; &nbsp; <th mat-header-cell *matHeaderCellDef>Contact Name</th>
&nbsp; &nbsp; &nbsp; &nbsp; <td mat-cell *matCellDef="let row">{{row.contactName}}</td>
&nbsp; &nbsp; &nbsp; </ng-container>

&nbsp; &nbsp; &nbsp; <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
&nbsp; &nbsp; &nbsp; <tr mat-row *matRowDef="let row; columns: displayedColumns;" [routerLink]="['/supplier-details/', row.supplierId]"></tr>
&nbsp; &nbsp; </table>
&nbsp; </div>
</div>

Finally, to make a little UI adjustment, open and edit src/app/supplier/supplier.component.css then add this CSS codes.

/* Structure */
.example-container {
&nbsp; &nbsp; position: relative;
&nbsp; &nbsp; padding: 5px;
&nbsp; }

&nbsp; .example-table-container {
&nbsp; &nbsp; position: relative;
&nbsp; &nbsp; max-height: 400px;
&nbsp; &nbsp; overflow: auto;
&nbsp; }

&nbsp; table {
&nbsp; &nbsp; width: 100%;
&nbsp; }

&nbsp; .example-loading-shade {
&nbsp; &nbsp; position: absolute;
&nbsp; &nbsp; top: 0;
&nbsp; &nbsp; left: 0;
&nbsp; &nbsp; bottom: 56px;
&nbsp; &nbsp; right: 0;
&nbsp; &nbsp; background: rgba(0, 0, 0, 0.15);
&nbsp; &nbsp; z-index: 1;
&nbsp; &nbsp; display: flex;
&nbsp; &nbsp; align-items: center;
&nbsp; &nbsp; justify-content: center;
&nbsp; }

&nbsp; .example-rate-limit-reached {
&nbsp; &nbsp; color: #980000;
&nbsp; &nbsp; max-width: 360px;
&nbsp; &nbsp; text-align: center;
&nbsp; }

&nbsp; /* Column Widths */
&nbsp; .mat-column-number,
&nbsp; .mat-column-state {
&nbsp; &nbsp; max-width: 64px;
&nbsp; }

&nbsp; .mat-column-created {
&nbsp; &nbsp; max-width: 124px;
&nbsp; }

&nbsp; .mat-flat-button {
&nbsp; &nbsp; margin: 5px;
&nbsp; }

13. Show and Delete Supplier Details using Angular 7 Material

To show supplier details after click or tap on the one of a row inside the Angular 7 Material table, open and edit src/app/supplier-detail/supplier-detail.component.ts then add this imports.

import { ActivatedRoute, Router } from '@angular/router';
import { ApiService } from '../api.service';
import { Supplier } from '../supplier';

Inject above modules to the constructor.

constructor(private route: ActivatedRoute, private api: ApiService, private router: Router) { }

Declare the variables before the constructor for hold supplier data that get from the API.

supplier: Supplier = {
&nbsp; supplierId: null,
&nbsp; companyName: '',
&nbsp; contactName: '',
&nbsp; contactTitle: '',
&nbsp; address: '',
&nbsp; city: '',
&nbsp; region: '',
&nbsp; postalCode: '',
&nbsp; country: '',
&nbsp; phone: '',
&nbsp; fax: '',
&nbsp; homePage: ''
};
isLoadingResults = true;

Add a function for getting Supplier data from the API.

getSupplierDetails(id) {
&nbsp; this.api.getSupplier(id)
&nbsp; &nbsp; .subscribe(data => {
&nbsp; &nbsp; &nbsp; this.supplier = data;
&nbsp; &nbsp; &nbsp; console.log(this.supplier);
&nbsp; &nbsp; &nbsp; this.isLoadingResults = false;
&nbsp; &nbsp; });
}

Call that function when the component is initiated.

ngOnInit() {
&nbsp; this.getSupplierDetails(this.route.snapshot.params['id']);
}

Add this function for delete supplier.

deleteSupplier(id: number) {
&nbsp; this.isLoadingResults = true;
&nbsp; this.api.deleteSupplier(id)
&nbsp; &nbsp; .subscribe(res => {
&nbsp; &nbsp; &nbsp; &nbsp; this.isLoadingResults = false;
&nbsp; &nbsp; &nbsp; &nbsp; this.router.navigate(['/supplier']);
&nbsp; &nbsp; &nbsp; }, (err) => {
&nbsp; &nbsp; &nbsp; &nbsp; console.log(err);
&nbsp; &nbsp; &nbsp; &nbsp; this.isLoadingResults = false;
&nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; );
}

For the view, open and edit src/app/supplier-detail/supplier-detail.component.html then replace all HTML tags with this.

<div class="example-container mat-elevation-z8">
&nbsp; <div class="example-loading-shade"
&nbsp; &nbsp; &nbsp; &nbsp;*ngIf="isLoadingResults">
&nbsp; &nbsp; <mat-spinner *ngIf="isLoadingResults"></mat-spinner>
&nbsp; </div>
&nbsp; <div class="button-row">
&nbsp; &nbsp; <a mat-flat-button color="primary" [routerLink]="['/supplier']"><mat-icon>list</mat-icon></a>
&nbsp; </div>
&nbsp; <mat-card class="example-card">
&nbsp; &nbsp; <mat-card-header>
&nbsp; &nbsp; &nbsp; <mat-card-title><h2>Supplier ID: {{supplier.supplierId}}</h2></mat-card-title>
&nbsp; &nbsp; &nbsp; <mat-card-subtitle>Company Name: {{supplier.companyName}}</mat-card-subtitle>
&nbsp; &nbsp; </mat-card-header>
&nbsp; &nbsp; <mat-card-content>
&nbsp; &nbsp; &nbsp; <dl>
&nbsp; &nbsp; &nbsp; &nbsp; <dt>Contact Name:</dt>
&nbsp; &nbsp; &nbsp; &nbsp; <dd>{{supplier.contactName}}</dd>
&nbsp; &nbsp; &nbsp; &nbsp; <dt>Contact Title:</dt>
&nbsp; &nbsp; &nbsp; &nbsp; <dd>{{supplier.contactTitle}}</dd>
&nbsp; &nbsp; &nbsp; &nbsp; <dt>Address:</dt>
&nbsp; &nbsp; &nbsp; &nbsp; <dd>{{supplier.address}}</dd>
&nbsp; &nbsp; &nbsp; &nbsp; <dt>City:</dt>
&nbsp; &nbsp; &nbsp; &nbsp; <dd>{{supplier.city}}</dd>
&nbsp; &nbsp; &nbsp; &nbsp; <dt>Region:</dt>
&nbsp; &nbsp; &nbsp; &nbsp; <dd>{{supplier.region}}</dd>
&nbsp; &nbsp; &nbsp; &nbsp; <dt>Postal Code:</dt>
&nbsp; &nbsp; &nbsp; &nbsp; <dd>{{supplier.postalCode}}</dd>
&nbsp; &nbsp; &nbsp; &nbsp; <dt>Country:</dt>
&nbsp; &nbsp; &nbsp; &nbsp; <dd>{{supplier.country}}</dd>
&nbsp; &nbsp; &nbsp; &nbsp; <dt>Phone:</dt>
&nbsp; &nbsp; &nbsp; &nbsp; <dd>{{supplier.phone}}</dd>
&nbsp; &nbsp; &nbsp; &nbsp; <dt>Fax:</dt>
&nbsp; &nbsp; &nbsp; &nbsp; <dd>{{supplier.fax}}</dd>
&nbsp; &nbsp; &nbsp; &nbsp; <dt>Home Page:</dt>
&nbsp; &nbsp; &nbsp; &nbsp; <dd>{{supplier.homePage}}</dd>
&nbsp; &nbsp; &nbsp; </dl>
&nbsp; &nbsp; </mat-card-content>
&nbsp; &nbsp; <mat-card-actions>
&nbsp; &nbsp; &nbsp; <a mat-flat-button color="primary" [routerLink]="['/supplier-edit/', supplier.supplierId || 'all']"><mat-icon>edit</mat-icon></a>
&nbsp; &nbsp; &nbsp; <a mat-flat-button color="warn" (click)="deleteSupplier(supplier.supplierId)"><mat-icon>delete</mat-icon></a>
&nbsp; &nbsp; </mat-card-actions>
&nbsp; </mat-card>
</div>

Finally, open and edit src/app/supplier-detail/supplier-detail.component.css then add these lines of CSS codes.

/* Structure */
.example-container {
&nbsp; position: relative;
&nbsp; padding: 5px;
}

.example-loading-shade {
&nbsp; position: absolute;
&nbsp; top: 0;
&nbsp; left: 0;
&nbsp; bottom: 56px;
&nbsp; right: 0;
&nbsp; background: rgba(0, 0, 0, 0.15);
&nbsp; z-index: 1;
&nbsp; display: flex;
&nbsp; align-items: center;
&nbsp; justify-content: center;
}

.mat-flat-button {
&nbsp; margin: 5px;
}

14. Add a Supplier using Angular 7 Material

To add a new supplier, we have to create Angular 7 reactive form. Open and edit src/app/supplier-add/supplier-add.component.ts then add this imports.

import { Router } from '@angular/router';
import { ApiService } from '../api.service';
import { FormControl, FormGroupDirective, FormBuilder, FormGroup, NgForm, Validators } from '@angular/forms';

Inject above modules to the constructor.

constructor(private router: Router, private api: ApiService, private formBuilder: FormBuilder) { }

Declare variables for the Form Group and all of the required fields inside the form before the constructor.

supplierForm: FormGroup;
companyName = '';
contactName = '';
contactTitle = '';
address = '';
city = '';
region = '';
postalCode = '';
country = '';
phone = '';
fax = '';
homePage = '';
isLoadingResults = false;

Add initial validation for each field.

ngOnInit() {
&nbsp; this.supplierForm = this.formBuilder.group({
&nbsp; &nbsp; 'companyName' : [null, Validators.required],
&nbsp; &nbsp; 'contactName' : [null, null],
&nbsp; &nbsp; 'contactTitle' : [null, null],
&nbsp; &nbsp; 'address' : [null, null],
&nbsp; &nbsp; 'city' : [null, null],
&nbsp; &nbsp; 'region' : [null, null],
&nbsp; &nbsp; 'postalCode' : [null, null],
&nbsp; &nbsp; 'country' : [null, null],
&nbsp; &nbsp; 'phone' : [null, null],
&nbsp; &nbsp; 'fax' : [null, null],
&nbsp; &nbsp; 'homePage' : [null, null]
&nbsp; });
}

Create a function for submitting or POST supplier form.

onFormSubmit(form: NgForm) {
&nbsp; this.isLoadingResults = true;
&nbsp; this.api.addSupplier(form)
&nbsp; &nbsp; .subscribe((res: { [x: string]: any; }) => {
&nbsp; &nbsp; &nbsp; &nbsp; const supplier = res['supplierResponse'];
&nbsp; &nbsp; &nbsp; &nbsp; const id = supplier['supplierId'];
&nbsp; &nbsp; &nbsp; &nbsp; this.isLoadingResults = false;
&nbsp; &nbsp; &nbsp; &nbsp; this.router.navigate(['/supplier-details', id]);
&nbsp; &nbsp; &nbsp; }, (err) => {
&nbsp; &nbsp; &nbsp; &nbsp; console.log(err);
&nbsp; &nbsp; &nbsp; &nbsp; this.isLoadingResults = false;
&nbsp; &nbsp; &nbsp; });
}

Next, add this import for implementing ErrorStateMatcher.

import { ErrorStateMatcher } from '@angular/material/core';

Create a new class after the end of this class bracket.

/** Error when invalid control is dirty, touched, or submitted. */
export class MyErrorStateMatcher implements ErrorStateMatcher {
&nbsp; isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
&nbsp; &nbsp; const isSubmitted = form && form.submitted;
&nbsp; &nbsp; return !!(control && control.invalid && (control.dirty || control.touched || isSubmitted));
&nbsp; }
}

Instantiate that MyErrorStateMatcher as a variable in main class.

matcher = new MyErrorStateMatcher();

Next, open and edit src/app/supplier-add/supplier-add.component.html then replace all HTML tags with this.

<div class="example-container mat-elevation-z8">
&nbsp; <div class="example-loading-shade"
&nbsp; &nbsp; &nbsp; &nbsp;*ngIf="isLoadingResults">
&nbsp; &nbsp; <mat-spinner *ngIf="isLoadingResults"></mat-spinner>
&nbsp; </div>
&nbsp; <div class="button-row">
&nbsp; &nbsp; <a mat-flat-button color="primary" [routerLink]="['/supplier']"><mat-icon>list</mat-icon></a>
&nbsp; </div>
&nbsp; <mat-card class="example-card">
&nbsp; &nbsp; <form [formGroup]="supplierForm" (ngSubmit)="onFormSubmit(supplierForm.value)">
&nbsp; &nbsp; &nbsp; <mat-form-field class="example-full-width">
&nbsp; &nbsp; &nbsp; &nbsp; <input matInput placeholder="Company Name" formControlName="companyName"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[errorStateMatcher]="matcher">
&nbsp; &nbsp; &nbsp; &nbsp; <mat-error>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span *ngIf="!supplierForm.get('companyName').valid && supplierForm.get('companyName').touched">Please enter Company Name</span>
&nbsp; &nbsp; &nbsp; &nbsp; </mat-error>
&nbsp; &nbsp; &nbsp; </mat-form-field>
&nbsp; &nbsp; &nbsp; <mat-form-field class="example-full-width">
&nbsp; &nbsp; &nbsp; &nbsp; <input matInput placeholder="Contact Name" formControlName="contactName"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[errorStateMatcher]="matcher">
&nbsp; &nbsp; &nbsp; </mat-form-field>
&nbsp; &nbsp; &nbsp; <mat-form-field class="example-full-width">
&nbsp; &nbsp; &nbsp; &nbsp; <input matInput placeholder="Contact Title" formControlName="contactTitle"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[errorStateMatcher]="matcher">
&nbsp; &nbsp; &nbsp; </mat-form-field>
&nbsp; &nbsp; &nbsp; <mat-form-field class="example-full-width">
&nbsp; &nbsp; &nbsp; &nbsp; <input matInput placeholder="Address" formControlName="address"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[errorStateMatcher]="matcher">
&nbsp; &nbsp; &nbsp; </mat-form-field>
&nbsp; &nbsp; &nbsp; <mat-form-field class="example-full-width">
&nbsp; &nbsp; &nbsp; &nbsp; <input matInput placeholder="City" formControlName="city"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[errorStateMatcher]="matcher">
&nbsp; &nbsp; &nbsp; </mat-form-field>
&nbsp; &nbsp; &nbsp; <mat-form-field class="example-full-width">
&nbsp; &nbsp; &nbsp; &nbsp; <input matInput placeholder="Region" formControlName="region"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[errorStateMatcher]="matcher">
&nbsp; &nbsp; &nbsp; </mat-form-field>
&nbsp; &nbsp; &nbsp; <mat-form-field class="example-full-width">
&nbsp; &nbsp; &nbsp; &nbsp; <input matInput placeholder="Postal Code" formControlName="postalCode"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[errorStateMatcher]="matcher">
&nbsp; &nbsp; &nbsp; </mat-form-field>
&nbsp; &nbsp; &nbsp; <mat-form-field class="example-full-width">
&nbsp; &nbsp; &nbsp; &nbsp; <input matInput placeholder="Country" formControlName="country"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[errorStateMatcher]="matcher">
&nbsp; &nbsp; &nbsp; </mat-form-field>
&nbsp; &nbsp; &nbsp; <mat-form-field class="example-full-width">
&nbsp; &nbsp; &nbsp; &nbsp; <input matInput placeholder="Phone" formControlName="phone"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[errorStateMatcher]="matcher">
&nbsp; &nbsp; &nbsp; </mat-form-field>
&nbsp; &nbsp; &nbsp; <mat-form-field class="example-full-width">
&nbsp; &nbsp; &nbsp; &nbsp; <input matInput placeholder="Fax" formControlName="fax"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[errorStateMatcher]="matcher">
&nbsp; &nbsp; &nbsp; </mat-form-field>
&nbsp; &nbsp; &nbsp; <mat-form-field class="example-full-width">
&nbsp; &nbsp; &nbsp; &nbsp; <input matInput placeholder="Home Page" formControlName="homePage"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[errorStateMatcher]="matcher">
&nbsp; &nbsp; &nbsp; </mat-form-field>
&nbsp; &nbsp; &nbsp; <div class="button-row">
&nbsp; &nbsp; &nbsp; &nbsp; <button type="submit" [disabled]="!supplierForm.valid" mat-flat-button color="primary"><mat-icon>save</mat-icon></button>
&nbsp; &nbsp; &nbsp; </div>
&nbsp; &nbsp; </form>
&nbsp; </mat-card>
</div>

Finally, open and edit src/app/supplier-add/supplier-add.component.css then add this CSS codes.

/* Structure */
.example-container {
&nbsp; position: relative;
&nbsp; padding: 5px;
}

.example-form {
&nbsp; min-width: 150px;
&nbsp; max-width: 500px;
&nbsp; width: 100%;
}

.example-full-width {
&nbsp; width: 100%;
}

.example-full-width:nth-last-child() {
&nbsp; margin-bottom: 10px;
}

.button-row {
&nbsp; margin: 10px 0;
}

.mat-flat-button {
&nbsp; margin: 5px;
}

15. Edit a Supplier using Angular 7 Material

We have put an edit button inside the Supplier Detail component for call Edit page. Now, open and edit src/app/supplier-edit/supplier-edit.component.ts then add this imports.

import { Router, ActivatedRoute } from '@angular/router';
import { ApiService } from '../api.service';
import { FormControl, FormGroupDirective, FormBuilder, FormGroup, NgForm, Validators } from '@angular/forms';
import { ErrorStateMatcher } from '@angular/material/core';

Inject above modules to the constructor.

constructor(private router: Router, private route: ActivatedRoute, private api: ApiService, private formBuilder: FormBuilder) { }

Declare the Form Group variable and all of the required variables for the supplier form before the constructor.

supplierForm: FormGroup;
companyName = '';
contactName = '';
contactTitle = '';
address = '';
city = '';
region = '';
postalCode = '';
country = '';
phone = '';
fax = '';
homePage = '';
isLoadingResults = false;
matcher = new MyErrorStateMatcher();

Next, add validation for all fields when the component is initiated.

ngOnInit() {
&nbsp; this.getSupplier(this.route.snapshot.params['id']);
&nbsp; this.supplierForm = this.formBuilder.group({
&nbsp; &nbsp; 'companyName' : [null, Validators.required],
&nbsp; &nbsp; 'contactName' : [null, null],
&nbsp; &nbsp; 'contactTitle' : [null, null],
&nbsp; &nbsp; 'address' : [null, null],
&nbsp; &nbsp; 'city' : [null, null],
&nbsp; &nbsp; 'region' : [null, null],
&nbsp; &nbsp; 'postalCode' : [null, null],
&nbsp; &nbsp; 'country' : [null, null],
&nbsp; &nbsp; 'phone' : [null, null],
&nbsp; &nbsp; 'fax' : [null, null],
&nbsp; &nbsp; 'homePage' : [null, null]
&nbsp; });
}

Create a function for getting supplier data that filled to each form fields.

getSupplier(id: number) {
&nbsp; this.api.getSupplier(id).subscribe(data => {
&nbsp; &nbsp; this.supplierId = data.supplierId;
&nbsp; &nbsp; this.supplierForm.setValue({
&nbsp; &nbsp; &nbsp; companyName: data.companyName,
&nbsp; &nbsp; &nbsp; contactName: data.contactName,
&nbsp; &nbsp; &nbsp; contactTitle: data.contactTitle,
&nbsp; &nbsp; &nbsp; address: data.address,
&nbsp; &nbsp; &nbsp; city: data.city,
&nbsp; &nbsp; &nbsp; region: data.region,
&nbsp; &nbsp; &nbsp; postalCode: data.postalCode,
&nbsp; &nbsp; &nbsp; country: data.country,
&nbsp; &nbsp; &nbsp; phone: data.phone,
&nbsp; &nbsp; &nbsp; fax: data.fax,
&nbsp; &nbsp; &nbsp; homePage: data.homePage
&nbsp; &nbsp; });
&nbsp; });
}

Create a function to update the supplier changes.

onFormSubmit(form: NgForm) {
&nbsp; this.isLoadingResults = true;
&nbsp; this.api.updateSupplier(this.supplierId, form)
&nbsp; &nbsp; .subscribe(res => {
&nbsp; &nbsp; &nbsp; &nbsp; this.isLoadingResults = false;
&nbsp; &nbsp; &nbsp; &nbsp; this.router.navigate(['/supplier']);
&nbsp; &nbsp; &nbsp; }, (err) => {
&nbsp; &nbsp; &nbsp; &nbsp; console.log(err);
&nbsp; &nbsp; &nbsp; &nbsp; this.isLoadingResults = false;
&nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; );
}

Add a function for handling show supplier details button.

supplierDetails() {
&nbsp; this.router.navigate(['/supplier-details', this.supplierId]);
}

Add a class that implementing ErrorStateMatcher after the current class.

/** Error when invalid control is dirty, touched, or submitted. */
export class MyErrorStateMatcher implements ErrorStateMatcher {
&nbsp; isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
&nbsp; &nbsp; const isSubmitted = form && form.submitted;
&nbsp; &nbsp; return !!(control && control.invalid && (control.dirty || control.touched || isSubmitted));
&nbsp; }
}

Next, open and edit src/app/supplier-edit/supplier-edit.component.html then replace all HTML tags with this.

<div class="example-container mat-elevation-z8">
&nbsp; <div class="example-loading-shade"
&nbsp; &nbsp; &nbsp; &nbsp;*ngIf="isLoadingResults">
&nbsp; &nbsp; <mat-spinner *ngIf="isLoadingResults"></mat-spinner>
&nbsp; </div>
&nbsp; <div class="button-row">
&nbsp; &nbsp; <a mat-flat-button color="primary" [routerLink]="['/supplier']"><mat-icon>list</mat-icon></a>
&nbsp; </div>
&nbsp; <mat-card class="example-card">
&nbsp; &nbsp; <form [formGroup]="supplierForm" (ngSubmit)="onFormSubmit(supplierForm.value)">
&nbsp; &nbsp; &nbsp; <mat-form-field class="example-full-width">
&nbsp; &nbsp; &nbsp; &nbsp; <input matInput placeholder="Company Name" formControlName="companyName"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[errorStateMatcher]="matcher">
&nbsp; &nbsp; &nbsp; &nbsp; <mat-error>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span *ngIf="!supplierForm.get('companyName').valid && supplierForm.get('companyName').touched">Please enter Company Name</span>
&nbsp; &nbsp; &nbsp; &nbsp; </mat-error>
&nbsp; &nbsp; &nbsp; </mat-form-field>
&nbsp; &nbsp; &nbsp; <mat-form-field class="example-full-width">
&nbsp; &nbsp; &nbsp; &nbsp; <input matInput placeholder="Contact Name" formControlName="contactName"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[errorStateMatcher]="matcher">
&nbsp; &nbsp; &nbsp; </mat-form-field>
&nbsp; &nbsp; &nbsp; <mat-form-field class="example-full-width">
&nbsp; &nbsp; &nbsp; &nbsp; <input matInput placeholder="Contact Title" formControlName="contactTitle"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[errorStateMatcher]="matcher">
&nbsp; &nbsp; &nbsp; </mat-form-field>
&nbsp; &nbsp; &nbsp; <mat-form-field class="example-full-width">
&nbsp; &nbsp; &nbsp; &nbsp; <input matInput placeholder="Address" formControlName="address"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[errorStateMatcher]="matcher">
&nbsp; &nbsp; &nbsp; </mat-form-field>
&nbsp; &nbsp; &nbsp; <mat-form-field class="example-full-width">
&nbsp; &nbsp; &nbsp; &nbsp; <input matInput placeholder="City" formControlName="city"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[errorStateMatcher]="matcher">
&nbsp; &nbsp; &nbsp; </mat-form-field>
&nbsp; &nbsp; &nbsp; <mat-form-field class="example-full-width">
&nbsp; &nbsp; &nbsp; &nbsp; <input matInput placeholder="Region" formControlName="region"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[errorStateMatcher]="matcher">
&nbsp; &nbsp; &nbsp; </mat-form-field>
&nbsp; &nbsp; &nbsp; <mat-form-field class="example-full-width">
&nbsp; &nbsp; &nbsp; &nbsp; <input matInput placeholder="Postal Code" formControlName="postalCode"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[errorStateMatcher]="matcher">
&nbsp; &nbsp; &nbsp; </mat-form-field>
&nbsp; &nbsp; &nbsp; <mat-form-field class="example-full-width">
&nbsp; &nbsp; &nbsp; &nbsp; <input matInput placeholder="Country" formControlName="country"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[errorStateMatcher]="matcher">
&nbsp; &nbsp; &nbsp; </mat-form-field>
&nbsp; &nbsp; &nbsp; <mat-form-field class="example-full-width">
&nbsp; &nbsp; &nbsp; &nbsp; <input matInput placeholder="Phone" formControlName="phone"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[errorStateMatcher]="matcher">
&nbsp; &nbsp; &nbsp; </mat-form-field>
&nbsp; &nbsp; &nbsp; <mat-form-field class="example-full-width">
&nbsp; &nbsp; &nbsp; &nbsp; <input matInput placeholder="Fax" formControlName="fax"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[errorStateMatcher]="matcher">
&nbsp; &nbsp; &nbsp; </mat-form-field>
&nbsp; &nbsp; &nbsp; <mat-form-field class="example-full-width">
&nbsp; &nbsp; &nbsp; &nbsp; <input matInput placeholder="Home Page" formControlName="homePage"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[errorStateMatcher]="matcher">
&nbsp; &nbsp; &nbsp; </mat-form-field>
&nbsp; &nbsp; &nbsp; <div class="button-row">
&nbsp; &nbsp; &nbsp; &nbsp; <button type="submit" [disabled]="!supplierForm.valid" mat-flat-button color="primary"><mat-icon>update</mat-icon></button>
&nbsp; &nbsp; &nbsp; </div>
&nbsp; &nbsp; </form>
&nbsp; </mat-card>
</div>

Finally, open and edit src/app/supplier-edit/supplier-edit.component.css then add this lines of CSS codes.

/* Structure */
.example-container {
&nbsp; position: relative;
&nbsp; padding: 5px;
}

.example-form {
&nbsp; min-width: 150px;
&nbsp; max-width: 500px;
&nbsp; width: 100%;
}

.example-full-width {
&nbsp; width: 100%;
}

.example-full-width:nth-last-child() {
&nbsp; margin-bottom: 10px;
}

.button-row {
&nbsp; margin: 10px 0;
}

.mat-flat-button {
&nbsp; margin: 5px;
}

16. Run and Test the ASP.NET Core Web API and Angular 7 CRUD Web Application

Before running the ASP.NET Core Web API that consumes by Angular 7 application, make sure ASP.NET Core Web API serve by HTTP only. Just open Properties\launchSettings.json then remove https from the applicationUrl. Next, type this command in the Visual Studio Code Terminal.

dotnet watch run

To run the Angular 7 application, type this command from the Node.js Command Prompt.

ng serve

Now, you will see this Angular 7 pages when pointing your browser to localhost:4200.

You can just navigate through the whole Angular 7 application.

That it’s, the tutorial of Building Web App using ASP.NET Web API Angular 7 and SQL Server. You can find the fully working source code from our GitHub.

Learn More

Angular 7 (formerly Angular 2) - The Complete Guide

Learn and Understand AngularJS

Angular Crash Course for Busy Developers

The Complete Angular Course: Beginner to Advanced

Angular (Angular 2+) & NodeJS - The MEAN Stack Guide

The Complete ASP.NET MVC 5 Course

Build a Real-world App with ASP.NET Core and Angular 2 (4+)

ASP NET Core (ASP.NET 5),MVC 6,C#,Angular2 & EF Crash Course

#angular #asp.net #sql-server

What is GEEK

Buddha Community

Building Web App using ASP.NET Web API Angular 7 and SQL Server
Einar  Hintz

Einar Hintz

1602560783

jQuery Ajax CRUD in ASP.NET Core MVC with Modal Popup

In this article, we’ll discuss how to use jQuery Ajax for ASP.NET Core MVC CRUD Operations using Bootstrap Modal. With jQuery Ajax, we can make HTTP request to controller action methods without reloading the entire page, like a single page application.

To demonstrate CRUD operations – insert, update, delete and retrieve, the project will be dealing with details of a normal bank transaction. GitHub repository for this demo project : https://bit.ly/33KTJAu.

Sub-topics discussed :

  • Form design for insert and update operation.
  • Display forms in modal popup dialog.
  • Form post using jQuery Ajax.
  • Implement MVC CRUD operations with jQuery Ajax.
  • Loading spinner in .NET Core MVC.
  • Prevent direct access to MVC action method.

Create ASP.NET Core MVC Project

In Visual Studio 2019, Go to File > New > Project (Ctrl + Shift + N).

From new project window, Select Asp.Net Core Web Application_._

Image showing how to create ASP.NET Core Web API project in Visual Studio.

Once you provide the project name and location. Select Web Application(Model-View-Controller) and uncheck HTTPS Configuration. Above steps will create a brand new ASP.NET Core MVC project.

Showing project template selection for .NET Core MVC.

Setup a Database

Let’s create a database for this application using Entity Framework Core. For that we’ve to install corresponding NuGet Packages. Right click on project from solution explorer, select Manage NuGet Packages_,_ From browse tab, install following 3 packages.

Showing list of NuGet Packages for Entity Framework Core

Now let’s define DB model class file – /Models/TransactionModel.cs.

public class TransactionModel
{
    [Key]
    public int TransactionId { get; set; }

    [Column(TypeName ="nvarchar(12)")]
    [DisplayName("Account Number")]
    [Required(ErrorMessage ="This Field is required.")]
    [MaxLength(12,ErrorMessage ="Maximum 12 characters only")]
    public string AccountNumber { get; set; }

    [Column(TypeName ="nvarchar(100)")]
    [DisplayName("Beneficiary Name")]
    [Required(ErrorMessage = "This Field is required.")]
    public string BeneficiaryName { get; set; }

    [Column(TypeName ="nvarchar(100)")]
    [DisplayName("Bank Name")]
    [Required(ErrorMessage = "This Field is required.")]
    public string BankName { get; set; }

    [Column(TypeName ="nvarchar(11)")]
    [DisplayName("SWIFT Code")]
    [Required(ErrorMessage = "This Field is required.")]
    [MaxLength(11)]
    public string SWIFTCode { get; set; }

    [DisplayName("Amount")]
    [Required(ErrorMessage = "This Field is required.")]
    public int Amount { get; set; }

    [DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}")]
    public DateTime Date { get; set; }
}

C#Copy

Here we’ve defined model properties for the transaction with proper validation. Now let’s define  DbContextclass for EF Core.

#asp.net core article #asp.net core #add loading spinner in asp.net core #asp.net core crud without reloading #asp.net core jquery ajax form #asp.net core modal dialog #asp.net core mvc crud using jquery ajax #asp.net core mvc with jquery and ajax #asp.net core popup window #bootstrap modal popup in asp.net core mvc. bootstrap modal popup in asp.net core #delete and viewall in asp.net core #jquery ajax - insert #jquery ajax form post #modal popup dialog in asp.net core #no direct access action method #update #validation in modal popup

Cayla  Erdman

Cayla Erdman

1594369800

Introduction to Structured Query Language SQL pdf

SQL stands for Structured Query Language. SQL is a scripting language expected to store, control, and inquiry information put away in social databases. The main manifestation of SQL showed up in 1974, when a gathering in IBM built up the principal model of a social database. The primary business social database was discharged by Relational Software later turning out to be Oracle.

Models for SQL exist. In any case, the SQL that can be utilized on every last one of the major RDBMS today is in various flavors. This is because of two reasons:

1. The SQL order standard is genuinely intricate, and it isn’t handy to actualize the whole standard.

2. Every database seller needs an approach to separate its item from others.

Right now, contrasts are noted where fitting.

#programming books #beginning sql pdf #commands sql #download free sql full book pdf #introduction to sql pdf #introduction to sql ppt #introduction to sql #practical sql pdf #sql commands pdf with examples free download #sql commands #sql free bool download #sql guide #sql language #sql pdf #sql ppt #sql programming language #sql tutorial for beginners #sql tutorial pdf #sql #structured query language pdf #structured query language ppt #structured query language

Top Enterprise Angular Web Apps Development Company in USA

AppClues Infotech is one of the leading Enterprise Angular Web Apps Development Company in USA. Our dedicated & highly experienced Angular app developers build top-grade Angular apps for your business with immersive technology & superior functionalities.

For more info:
Website: https://www.appcluesinfotech.com/
Email: info@appcluesinfotech.com
Call: +1-978-309-9910

#top enterprise angular web apps development company in usa #enterprise angular web apps development #hire enterprise angular web apps developers #best enterprise angular web app services #custom enterprise angular web apps solution #professional enterprise angular web apps developers

Ray  Patel

Ray Patel

1625843760

Python Packages in SQL Server – Get Started with SQL Server Machine Learning Services

Introduction

When installing Machine Learning Services in SQL Server by default few Python Packages are installed. In this article, we will have a look on how to get those installed python package information.

Python Packages

When we choose Python as Machine Learning Service during installation, the following packages are installed in SQL Server,

  • revoscalepy – This Microsoft Python package is used for remote compute contexts, streaming, parallel execution of rx functions for data import and transformation, modeling, visualization, and analysis.
  • microsoftml – This is another Microsoft Python package which adds machine learning algorithms in Python.
  • Anaconda 4.2 – Anaconda is an opensource Python package

#machine learning #sql server #executing python in sql server #machine learning using python #machine learning with sql server #ml in sql server using python #python in sql server ml #python packages #python packages for machine learning services #sql server machine learning services

Dylan  Iqbal

Dylan Iqbal

1560822820

Building Web App using ASP.NET Web API Angular 7 and SQL Server

The comprehensive step by step tutorial on building Web Application using ASP.NET Web API, Angular 7 and Microsoft SQL Server. In this tutorial, we will create a RESTful API web service using ASP.NET Core Web API then create a front-end application with Angular 7. For the backend, we use Microsoft SQL Server 2017 Express Edition with the additional database Northwind. This is our first ASP.NET tutorial, so there will be many shortcomings and a lot of discussions.

Table of Contents:

The following tools, frameworks, package, and modules are required for this tutorial:

We assume that you already install all above required tools. Now, we have to check that DotNet SDK already installed and added to the path. Open command prompt then type this command to make sure DotNet installed and runnable via command prompt.

dotnet --version

You will get this result.

2.1.403

We are using DotNet Framework SDK version 2.1.403. That’s mean you’re ready to move to the main steps.

1. Download and Install Northwind Sample Database

To download Northwind sample database for SQL Server 2017, open your browser then go to this link https://northwinddatabase.codeplex.com/. After download, extract to your root folder (for example C:). Next, open Microsoft SQL Server Management Studio. Login to your local Server then right-click Database in the Object Explorer Window then choose Restore Database.

Choose Device then Click … button. The select device dialog will open then click Add button, browse to the .bak file that previously extracted then click OK button then click again OK button.

Click OK button to Restore the Northwind Database. Now, you should see the Northwind Database in the Database.

2. Create and Configure a new ASP.NET Web API Application

A slightly different of ASP.NET Core application creation, we will use the command prompt. Of course, you can use the more easiest way when using Microsoft Visual Studio. In the command prompt go to your projects folder then type this command.

dotnet &nbsp;new webapi –o AspNetAngular –n AspNetAngular

You will the output like below in the Command Prompt.

The template "ASP.NET Core Web API" was created successfully.

Processing post-creation actions...
Running 'dotnet restore' on AspNetAngular\AspNetAngular.csproj...
&nbsp; Restoring packages for C:\Users\DIDIN\Projects\AspNetAngular\AspNetAngular.csproj...
&nbsp; Generating MSBuild file C:\Users\DIDIN\Projects\AspNetAngular\obj\AspNetAngular.csproj.nuget.g.props.
&nbsp; Generating MSBuild file C:\Users\DIDIN\Projects\AspNetAngular\obj\AspNetAngular.csproj.nuget.g.targets.
&nbsp; Restore completed in 5.82 sec for C:\Users\DIDIN\Projects\AspNetAngular\AspNetAngular.csproj.

Restore succeeded.

That’s mean, you can open directly as a folder from Visual Studio Code as well as CSharp Project/Solution from Microsoft Visual Studio. Or you can call this new ASP.NET Core Web API Project by type this command.

cd AspNetAngular
code .

The project will be opened by Visual Studio Code. If you get a notification like below just click Yes button.

Next, open terminal from the menu or press Ctrl+Shift+`. Run these commands to installs all required packages

dotnet add package Microsoft.EntityFrameworkCore.Tools -v 2.1.2
dotnet add package Microsoft.EntityFrameworkCore.SqlServer -v 2.1.2
dotnet add package Microsoft.EntityFrameworkCore.SqlServer.Design -v 1.1.6
dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design -v 2.1.5
dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Tools -v 2.0.4
dotnet add package AutoMapper.Extensions.Microsoft.DependencyInjection -v 5.0.1

If you see a notification like below, just click Restore button.

Now, you will have this packages with the right version installed shown in AspNetAngular.csproj file.

<ItemGroup>
&nbsp; <PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="6.0.0" />
&nbsp; <PackageReference Include="Microsoft.AspNetCore.App" />
&nbsp; <PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.1.2" PrivateAssets="All" />
&nbsp; <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="2.1.2" />
&nbsp; <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer.Design" Version="1.1.6" />
&nbsp; <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="2.1.2">
&nbsp; &nbsp; <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
&nbsp; &nbsp; <PrivateAssets>all</PrivateAssets>
&nbsp; </PackageReference>
&nbsp; <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.1.5" />
&nbsp; <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.4" />
</ItemGroup>

Next, build the DotNet application to make sure there’s no error in package dependencies.

dotnet build

You must see this output when everything on the right path.

Build succeeded.
&nbsp; &nbsp; 0 Warning(s)
&nbsp; &nbsp; 0 Error(s)

Next, we have to configure connections to Microsoft SQL Server Database. First, open and edit appsettings.json then add this lines before logging JSON object.

"ConnectionStrings": {
&nbsp; "SQLConnection": "Server=.;Database=NORTHWND;Trusted_Connection=True;User Id=sa;Password=q;Integrated Security=false;MultipleActiveResultSets=true"
},

Open and edit Startup.cs then add this line inside ConfigureServices bracket.

services.AddDbContext<NORTHWNDContext>(options => options.UseSqlServer(Configuration.GetConnectionString("SQLConnection")));

Next, add this line to enable CORS after above line.

services.AddCors();

Also, add this line inside Configure bracket.

app.UseCors(x => x.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod());

Don’t forget to import the library or module that added in the Configuration.

3. Generate Models from Microsoft SQL Server Database

We will use the Code Generation Tools package to generate all models that represent all tables in the Northwind Database. Run this command to generate the models and their context.

dotnet ef dbcontext scaffold "Server=.;Database=NORTHWND;Trusted_Connection=True;User Id=sa;Password=q;Integrated Security=false;" Microsoft.EntityFrameworkCore.SqlServer -o Models

You will see the generated Models and Context inside the Models folder.

If there’s a lot of warning or error that comes from IDE linter, just re-open the Visual Studio Code. As you see in the table of contents, we will use only Supplier model for this tutorial. The generated suppliers look like this.

using System;
using System.Collections.Generic;

namespace AspNetAngular.Models
{
&nbsp; &nbsp; public partial class Suppliers
&nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; public Suppliers()
&nbsp; &nbsp; &nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Products = new HashSet<Products>();
&nbsp; &nbsp; &nbsp; &nbsp; }

&nbsp; &nbsp; &nbsp; &nbsp; public int SupplierId { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string CompanyName { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string ContactName { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string ContactTitle { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string Address { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string City { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string Region { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string PostalCode { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string Country { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string Phone { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string Fax { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string HomePage { get; set; }

&nbsp; &nbsp; &nbsp; &nbsp; public ICollection<Products> Products { get; set; }
&nbsp; &nbsp; }
}

That model declared in the NORTHWNDContext.cs the file inside Models folder.

public virtual DbSet<Suppliers> Suppliers { get; set; }

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
&nbsp; modelBuilder.Entity<Suppliers>(entity =>
&nbsp; {
&nbsp; &nbsp; &nbsp; entity.HasKey(e => e.SupplierId);

&nbsp; &nbsp; &nbsp; entity.HasIndex(e => e.CompanyName)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .HasName("CompanyName");

&nbsp; &nbsp; &nbsp; entity.HasIndex(e => e.PostalCode)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .HasName("PostalCode");

&nbsp; &nbsp; &nbsp; entity.Property(e => e.SupplierId).HasColumnName("SupplierID");

&nbsp; &nbsp; &nbsp; entity.Property(e => e.Address).HasMaxLength(60);

&nbsp; &nbsp; &nbsp; entity.Property(e => e.City).HasMaxLength(15);

&nbsp; &nbsp; &nbsp; entity.Property(e => e.CompanyName)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .IsRequired()
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .HasMaxLength(40);

&nbsp; &nbsp; &nbsp; entity.Property(e => e.ContactName).HasMaxLength(30);

&nbsp; &nbsp; &nbsp; entity.Property(e => e.ContactTitle).HasMaxLength(30);

&nbsp; &nbsp; &nbsp; entity.Property(e => e.Country).HasMaxLength(15);

&nbsp; &nbsp; &nbsp; entity.Property(e => e.Fax).HasMaxLength(24);

&nbsp; &nbsp; &nbsp; entity.Property(e => e.HomePage).HasColumnType("ntext");

&nbsp; &nbsp; &nbsp; entity.Property(e => e.Phone).HasMaxLength(24);

&nbsp; &nbsp; &nbsp; entity.Property(e => e.PostalCode).HasMaxLength(10);

&nbsp; &nbsp; &nbsp; entity.Property(e => e.Region).HasMaxLength(15);
&nbsp; });
}

4. Create DTO (Data Transfer Object) for Request Body and Response

To specify request body and response fields, we will use a Data Transfer Object (DTO). For that, create a new DTOs folder and AddSupplierDto.cs, EditSupplierDto.cs, SupplierResponse.cs files inside that folder. Next, open and edit AddSupplierDto.cs then Replace all codes with this.

using System;
using System.ComponentModel.DataAnnotations;

namespace AspNetAngular.Dtos
{
&nbsp; &nbsp; public class AddSupplierDto
&nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; [Required]
&nbsp; &nbsp; &nbsp; &nbsp; public string CompanyName { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string ContactName { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string ContactTitle { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string Address { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string City { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string Region { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string PostalCode { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string Country { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string Phone { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string Fax { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string HomePage { get; set; }
&nbsp; &nbsp; }
}

Next, open and edit EditSupplierDto.cs then Replace all codes with this.

using System;
using System.ComponentModel.DataAnnotations;

namespace AspNetAngular.Dtos
{
&nbsp; &nbsp; public class EditSupplierDto
&nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; [Required]
&nbsp; &nbsp; &nbsp; &nbsp; public int SupplierId { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; [Required]
&nbsp; &nbsp; &nbsp; &nbsp; public string CompanyName { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string ContactName { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string ContactTitle { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string Address { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string City { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string Region { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string PostalCode { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string Country { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string Phone { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string Fax { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string HomePage { get; set; }
&nbsp; &nbsp; }
}

Next, open and edit SupplierResponseDto.cs then Replace all codes with this.

namespace AspNetAngular.Dtos
{
&nbsp; &nbsp; public class SupplierResponseDto
&nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; public int SupplierId { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string CompanyName { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string ContactName { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string ContactTitle { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string Address { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string City { get; set; }
&nbsp; &nbsp; &nbsp; &nbsp; public string PostalCode { get; set; }

&nbsp; &nbsp; }
}

5. Create Helpers Class for Mapping DTO with Model Classes

To create a helper for mapping DTO to Model classes, create the folder Helpers in the root of project folder then create a file AutoMapperProfile.cs inside that new folder. Open and edit this new file then replace all codes with this.

using AspNetAngular.Dtos;
using AspNetAngular.Models;
using AutoMapper;

namespace AspNetAngular.Helpers
{
&nbsp; &nbsp; public class AutoMapperProfiles: Profile
&nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; public AutoMapperProfiles()
&nbsp; &nbsp; &nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CreateMap<AddSupplierDto, Suppliers>();
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CreateMap<EditSupplierDto, Suppliers>();
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CreateMap<Suppliers, SupplierResponseDto>();
&nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; }
}

Next, open and edit again Startup.cs then add this line inside ConfigureServices.

services.AddAutoMapper();

Don’t forget to auto import the library in ConfigureServices.

6. Create Repositories for CRUD (Create, Read, Update Delete) Operations

To create a repository class and interface, we have to create a folder Repositories in the root of the project folder. Next, create an interface file inside that folder with the name IDataRepository.cs then replace all codes with this.

using System.Threading.Tasks;

namespace AspNetAngular.Repositories
{
&nbsp; &nbsp; public interface IDataRepository<T> where T : class
&nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; void Add(T entity);
&nbsp; &nbsp; &nbsp; &nbsp; void Update(T entity);
&nbsp; &nbsp; &nbsp; &nbsp; void Delete(T entity);
&nbsp; &nbsp; &nbsp; &nbsp; Task<T> SaveAsync(T entity);
&nbsp; &nbsp; }
}

Next, create a file inside that folder with the name DataRepository.cs then replace all codes with this.

using System.Threading.Tasks;
using AspNetAngular.Models;

namespace AspNetAngular.Repositories
{
&nbsp; &nbsp; public class DataRepository<T> : IDataRepository<T> where T : class
&nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; private readonly NORTHWNDContext _context;

&nbsp; &nbsp; &nbsp; &nbsp; public DataRepository(NORTHWNDContext context)
&nbsp; &nbsp; &nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _context = context;
&nbsp; &nbsp; &nbsp; &nbsp; }

&nbsp; &nbsp; &nbsp; &nbsp; public void Add(T entity)
&nbsp; &nbsp; &nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _context.Set<T>().Add(entity);
&nbsp; &nbsp; &nbsp; &nbsp; }

&nbsp; &nbsp; &nbsp; &nbsp; public void Update(T entity)
&nbsp; &nbsp; &nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _context.Set<T>().Update(entity);
&nbsp; &nbsp; &nbsp; &nbsp; }

&nbsp; &nbsp; &nbsp; &nbsp; public void Delete(T entity)
&nbsp; &nbsp; &nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _context.Set<T>().Remove(entity);
&nbsp; &nbsp; &nbsp; &nbsp; }

&nbsp; &nbsp; &nbsp; &nbsp; public async Task<T> SaveAsync(T entity)
&nbsp; &nbsp; &nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; await _context.SaveChangesAsync();
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return entity;
&nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; }
}

Next, open and edit again Startup.cs then add this line inside ConfigureServices bracket.

services.AddScoped(typeof(IDataRepository < > ), typeof(DataRepository < > ));

Also, import the required classes and libraries.

7. Create Controller for CRUD Operations

Now, we will show you how the API available via Controller. We will generate a controller for Supplier model. Before generate, we have to install the tools for it. Run this command in the terminal of Visual Studio Code.

dotnet tool install --global dotnet-aspnet-codegenerator --version 2.2.1

Just run this command to generate it.

dotnet aspnet-codegenerator controller -name SupplierController -api -async -m AspNetAngular.Models.Suppliers -dc NORTHWNDContext -namespace AspNetAngular.Controllers -outDir Controllers

Now, we have a Supplier’s controller that looks like this.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using AspNetAngular.Models;

namespace AspNetAngular.Controllers
{
&nbsp; &nbsp; [Route("api/[controller]")]
&nbsp; &nbsp; [ApiController]
&nbsp; &nbsp; public class SupplierController : ControllerBase
&nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; private readonly NORTHWNDContext _context;

&nbsp; &nbsp; &nbsp; &nbsp; public SupplierController(NORTHWNDContext context)
&nbsp; &nbsp; &nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _context = context;
&nbsp; &nbsp; &nbsp; &nbsp; }

&nbsp; &nbsp; &nbsp; &nbsp; // GET: api/Supplier
&nbsp; &nbsp; &nbsp; &nbsp; [HttpGet]
&nbsp; &nbsp; &nbsp; &nbsp; public IEnumerable<Suppliers> GetSuppliers()
&nbsp; &nbsp; &nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return _context.Suppliers;
&nbsp; &nbsp; &nbsp; &nbsp; }

&nbsp; &nbsp; &nbsp; &nbsp; // GET: api/Supplier/5
&nbsp; &nbsp; &nbsp; &nbsp; [HttpGet("{id}")]
&nbsp; &nbsp; &nbsp; &nbsp; public async Task<IActionResult> GetSuppliers([FromRoute] int id)
&nbsp; &nbsp; &nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (!ModelState.IsValid)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return BadRequest(ModelState);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var suppliers = await _context.Suppliers.FindAsync(id);

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (suppliers == null)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return NotFound();
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return Ok(suppliers);
&nbsp; &nbsp; &nbsp; &nbsp; }

&nbsp; &nbsp; &nbsp; &nbsp; // PUT: api/Supplier/5
&nbsp; &nbsp; &nbsp; &nbsp; [HttpPut("{id}")]
&nbsp; &nbsp; &nbsp; &nbsp; public async Task<IActionResult> PutSuppliers([FromRoute] int id, [FromBody] Suppliers suppliers)
&nbsp; &nbsp; &nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (!ModelState.IsValid)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return BadRequest(ModelState);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (id != suppliers.SupplierId)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return BadRequest();
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _context.Entry(suppliers).State = EntityState.Modified;

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; try
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; await _context.SaveChangesAsync();
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; catch (DbUpdateConcurrencyException)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (!SuppliersExists(id))
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return NotFound();
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; else
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return NoContent();
&nbsp; &nbsp; &nbsp; &nbsp; }

&nbsp; &nbsp; &nbsp; &nbsp; // POST: api/Supplier
&nbsp; &nbsp; &nbsp; &nbsp; [HttpPost]
&nbsp; &nbsp; &nbsp; &nbsp; public async Task<IActionResult> PostSuppliers([FromBody] Suppliers suppliers)
&nbsp; &nbsp; &nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (!ModelState.IsValid)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return BadRequest(ModelState);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _context.Suppliers.Add(suppliers);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; await _context.SaveChangesAsync();

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return CreatedAtAction("GetSuppliers", new { id = suppliers.SupplierId }, suppliers);
&nbsp; &nbsp; &nbsp; &nbsp; }

&nbsp; &nbsp; &nbsp; &nbsp; // DELETE: api/Supplier/5
&nbsp; &nbsp; &nbsp; &nbsp; [HttpDelete("{id}")]
&nbsp; &nbsp; &nbsp; &nbsp; public async Task<IActionResult> DeleteSuppliers([FromRoute] int id)
&nbsp; &nbsp; &nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (!ModelState.IsValid)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return BadRequest(ModelState);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var suppliers = await _context.Suppliers.FindAsync(id);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (suppliers == null)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return NotFound();
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _context.Suppliers.Remove(suppliers);
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; await _context.SaveChangesAsync();

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return Ok(suppliers);
&nbsp; &nbsp; &nbsp; &nbsp; }

&nbsp; &nbsp; &nbsp; &nbsp; private bool SuppliersExists(int id)
&nbsp; &nbsp; &nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return _context.Suppliers.Any(e => e.SupplierId == id);
&nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; }
}

As you see that generated Controllers using original fields from the Suppliers Model. Next, we will use our previous created DTO for custom Object save, edit and their response. Open and edit Controllers/SupplierController.cs then add this variable after context variable.

private readonly IMapper _mapper;
private readonly IDataRepository<Suppliers> _repo;

Also, inject to the SupplierController constructor.

public SupplierController(NORTHWNDContext context, IMapper mapper, IDataRepository<Suppliers> repo)
{
&nbsp; &nbsp; _context = context;
&nbsp; &nbsp; _mapper = mapper;
&nbsp; &nbsp; _repo = repo;
}

Don’t forget to import all required libraries or classes. Next, replace the HTTPPost method with this codes.

// POST: api/Supplier
[HttpPost]
public async Task<IActionResult> PostSuppliers([FromBody] AddSupplierDto addSupplierDto)
{
&nbsp; &nbsp; if (!ModelState.IsValid)
&nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; return BadRequest(ModelState);
&nbsp; &nbsp; }

&nbsp; &nbsp; var preSupplier = _mapper.Map<Suppliers>(addSupplierDto);
&nbsp; &nbsp; _repo.Add(preSupplier);
&nbsp; &nbsp; var saveSupplier = await _repo.SaveAsync(preSupplier);
&nbsp; &nbsp; var supplierResponse = _mapper.Map<SupplierResponseDto>(saveSupplier);

&nbsp; &nbsp; return StatusCode(201, new { supplierResponse });
}

Next, replace the HTTPPut method with this codes.

// PUT: api/Supplier/5
[HttpPut("{id}")]
public async Task<IActionResult> PutSuppliers([FromRoute] int id, [FromBody] EditSupplierDto editSupplierDto)
{
&nbsp; &nbsp; if (!ModelState.IsValid)
&nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; return BadRequest(ModelState);
&nbsp; &nbsp; }

&nbsp; &nbsp; if (id != editSupplierDto.SupplierId)
&nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; return BadRequest();
&nbsp; &nbsp; }

&nbsp; &nbsp; var preSupplier = _mapper.Map<Suppliers>(editSupplierDto);
&nbsp; &nbsp; _repo.Update(preSupplier);
&nbsp; &nbsp; await _repo.SaveAsync(preSupplier);

&nbsp; &nbsp; return NoContent();
}

Finally, replace the HTTPDelete method with this because we will delete manually busing SQL Query the related table.

// DELETE: api/Supplier/5
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteSuppliers([FromRoute] int id)
{
&nbsp; &nbsp; if (!ModelState.IsValid)
&nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; return BadRequest(ModelState);
&nbsp; &nbsp; }

&nbsp; &nbsp; var suppliers = await _context.Suppliers.FindAsync(id);

&nbsp; &nbsp; if (suppliers == null)
&nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; return NotFound();
&nbsp; &nbsp; }

&nbsp; &nbsp; _context.Database.ExecuteSqlCommand("DELETE FROM [Order Details] WHERE ProductID IN (SELECT ProductID FROM Products WHERE SupplierID = @supplierId)",
&nbsp; &nbsp; &nbsp; &nbsp; new SqlParameter("@supplierId", suppliers.SupplierId));

&nbsp; &nbsp; _context.Database.ExecuteSqlCommand("DELETE FROM Products WHERE SupplierID = @supplierId",
&nbsp; &nbsp; &nbsp; &nbsp; new SqlParameter("@supplierId", suppliers.SupplierId));

&nbsp; &nbsp; _context.Suppliers.Remove(suppliers);
&nbsp; &nbsp; await _context.SaveChangesAsync();

&nbsp; &nbsp; return Ok(suppliers);
}

8. Test API using Postman

Now, we have to run the ASP.NET Core Web API from the Terminal by typing this command.

dotnet watch run

Watch keyword is the additional command for monitoring any change in the codes then reloading the ASP.NET Core Web API application. Next, open or run the Postman application. Use the GET method and fill the right column after the GET method with localhost:5000/api/Supplier, Headers key with Content-Type, Headers value with application/json.

Now, click the Send button and you should see this result for successful GET Supplier.

[
&nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; "supplierId": 1,
&nbsp; &nbsp; &nbsp; &nbsp; "companyName": "Exotic Liquids",
&nbsp; &nbsp; &nbsp; &nbsp; "contactName": "Charlotte Cooper",
&nbsp; &nbsp; &nbsp; &nbsp; "contactTitle": "Purchasing Manager",
&nbsp; &nbsp; &nbsp; &nbsp; "address": "49 Gilbert St.",
&nbsp; &nbsp; &nbsp; &nbsp; "city": "London",
&nbsp; &nbsp; &nbsp; &nbsp; "region": null,
&nbsp; &nbsp; &nbsp; &nbsp; "postalCode": "EC1 4SD",
&nbsp; &nbsp; &nbsp; &nbsp; "country": "UK",
&nbsp; &nbsp; &nbsp; &nbsp; "phone": "(171) 555-2222",
&nbsp; &nbsp; &nbsp; &nbsp; "fax": null,
&nbsp; &nbsp; &nbsp; &nbsp; "homePage": null,
&nbsp; &nbsp; &nbsp; &nbsp; "products": []
&nbsp; &nbsp; },
&nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; "supplierId": 2,
&nbsp; &nbsp; &nbsp; &nbsp; "companyName": "New Orleans Cajun Delights",
&nbsp; &nbsp; &nbsp; &nbsp; "contactName": "Shelley Burke",
&nbsp; &nbsp; &nbsp; &nbsp; "contactTitle": "Order Administrator",
&nbsp; &nbsp; &nbsp; &nbsp; "address": "P.O. Box 78934",
&nbsp; &nbsp; &nbsp; &nbsp; "city": "New Orleans",
&nbsp; &nbsp; &nbsp; &nbsp; "region": "LA",
&nbsp; &nbsp; &nbsp; &nbsp; "postalCode": "70117",
&nbsp; &nbsp; &nbsp; &nbsp; "country": "USA",
&nbsp; &nbsp; &nbsp; &nbsp; "phone": "(100) 555-4822",
&nbsp; &nbsp; &nbsp; &nbsp; "fax": null,
&nbsp; &nbsp; &nbsp; &nbsp; "homePage": "#CAJUN.HTM#",
&nbsp; &nbsp; &nbsp; &nbsp; "products": []
&nbsp; &nbsp; },
&nbsp; &nbsp; ...
]

To get single supplier by supplier ID, just change the URL to this localhost:5000/api/Supplier/2. If found, you will see the result of a single supplier. Next, for POST a Supplier changes the method to POST, leave URL same as the GET supplier list then fill the body with a raw JSON object.

{
&nbsp; "CompanyName": "Djamware Inc.",
&nbsp; "ContactName": "Didin J.",
&nbsp; "ContactTitle": "CEO",
&nbsp; "Address": "Whereever Road 123",
&nbsp; "City": "Bandung",
&nbsp; "Region": "JBR",
&nbsp; "PostalCode": "12345",
&nbsp; "Country": "Indonesia",
&nbsp; "Phone": "(022) 123-4567890",
&nbsp; "Fax": "(022) 123-4567890",
&nbsp; "HomePage": "https://www.djamware.com"
}

You will see this result with status 201.

{
&nbsp; &nbsp; "supplierResponse": {
&nbsp; &nbsp; &nbsp; &nbsp; "companyName": "Djamware Inc.",
&nbsp; &nbsp; &nbsp; &nbsp; "contactName": "Didin J.",
&nbsp; &nbsp; &nbsp; &nbsp; "contactTitle": "CEO",
&nbsp; &nbsp; &nbsp; &nbsp; "address": "Whereever Road 123",
&nbsp; &nbsp; &nbsp; &nbsp; "city": "Bandung",
&nbsp; &nbsp; &nbsp; &nbsp; "region": "JBR",
&nbsp; &nbsp; &nbsp; &nbsp; "postalCode": "12345",
&nbsp; &nbsp; &nbsp; &nbsp; "country": "Indonesia",
&nbsp; &nbsp; &nbsp; &nbsp; "phone": "(022) 123-4567890",
&nbsp; &nbsp; &nbsp; &nbsp; "fax": "(022) 123-4567890",
&nbsp; &nbsp; &nbsp; &nbsp; "homePage": "https://www.djamware.com"
&nbsp; &nbsp; }
}

To update the Supplier data, change the method to PUT and URL to localhost:5000/api/Supplier/30 then add a supplier id field to the raw body.

{
&nbsp; "SupplierId": 30,
&nbsp; "CompanyName": "Djamware.com",
&nbsp; "ContactName": "Didin J.",
&nbsp; "ContactTitle": "Engineer",
&nbsp; "Address": "Whereever Road 123",
&nbsp; "City": "Garut",
&nbsp; "Region": "JBR",
&nbsp; "PostalCode": "12345",
&nbsp; "Country": "Indonesia",
&nbsp; "Phone": "(022) 123-4567890",
&nbsp; "Fax": "(022) 123-4567890",
&nbsp; "HomePage": "https://www.djamware.com"
}

The response should be 204 (No Content) for a successful request. Next, for delete a supplier, simply change the method to DELETE, keep the URL as the previous method and change the body to none. You should see the 200 response and data that deleted in the response body.

9. Install or Update Angular 7 CLI and Create Application

Before installing the Angular 7 CLI, make sure you have installed Node.js https://nodejs.org and can open Node.js command prompt. Next, open the Node.js command prompt then type this command to install Angular 7 CLI.

npm install -g @angular/cli

Next, create an Angular 7 application by typing this command in the root of ASP.NET Core application/project directory.

ng new client

Where client is the name of the Angular 7 application. You can specify your own name, we like to name it client because it’s put inside ASP.NET Core Project directory. If there’s a question, we fill them with Y and SASS. Next, go to the newly created Angular 7 application.

cd client

Run the Angular 7 application for the first time.

ng serve

Now, go to localhost:4200 and you should see this page.

To stop the Angular 7 application, just press CTRL+C keys.

10. Add Routes for Navigation between Angular 7 Pages/Component

On the previous steps, we have to added Angular 7 Routes when answering the questions. Now, we just added the required pages for CRUD (Create, Read, Update, Delete) Supplier data. Type this commands to add the Angular 7 components or pages.

ng g component supplier
ng g component supplier-detail
ng g component supplier-add
ng g component supplier-edit

Open src/app/app.module.ts then you will see those components imported and declared in @NgModule declarations. Next, open and edit src/app/app-routing.module.ts then add this imports.

import { SupplierComponent } from './supplier/supplier.component';
import { SupplierDetailComponent } from './supplier-detail/supplier-detail.component';
import { SupplierAddComponent } from './supplier-add/supplier-add.component';
import { SupplierEditComponent } from './supplier-edit/supplier-edit.component';

Add these arrays to the existing routes constant.

const routes: Routes = [
&nbsp; {
&nbsp; &nbsp; path: 'supplier',
&nbsp; &nbsp; component: SupplierComponent,
&nbsp; &nbsp; data: { title: 'List of Suppliers' }
&nbsp; },
&nbsp; {
&nbsp; &nbsp; path: 'supplier-details/:id',
&nbsp; &nbsp; component: SupplierDetailComponent,
&nbsp; &nbsp; data: { title: 'Supplier Details' }
&nbsp; },
&nbsp; {
&nbsp; &nbsp; path: 'supplier-add',
&nbsp; &nbsp; component: SupplierAddComponent,
&nbsp; &nbsp; data: { title: 'Add Supplier' }
&nbsp; },
&nbsp; {
&nbsp; &nbsp; path: 'supplier-edit/:id',
&nbsp; &nbsp; component: SupplierEditComponent,
&nbsp; &nbsp; data: { title: 'Edit Supplier' }
&nbsp; },
&nbsp; { path: '',
&nbsp; &nbsp; redirectTo: '/supplier',
&nbsp; &nbsp; pathMatch: 'full'
&nbsp; }
];

Open and edit src/app/app.component.html and you will see existing router outlet. Next, modify this HTML page to fit the CRUD page.

<div style="text-align:center">
&nbsp; <h1>
&nbsp; &nbsp; Welcome to {{ title }}!
&nbsp; </h1>
&nbsp; <img width="300" alt="Angular Logo" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTAgMjUwIj4KICAgIDxwYXRoIGZpbGw9IiNERDAwMzEiIGQ9Ik0xMjUgMzBMMzEuOSA2My4ybDE0LjIgMTIzLjFMMTI1IDIzMGw3OC45LTQzLjcgMTQuMi0xMjMuMXoiIC8+CiAgICA8cGF0aCBmaWxsPSIjQzMwMDJGIiBkPSJNMTI1IDMwdjIyLjItLjFWMjMwbDc4LjktNDMuNyAxNC4yLTEyMy4xTDEyNSAzMHoiIC8+CiAgICA8cGF0aCAgZmlsbD0iI0ZGRkZGRiIgZD0iTTEyNSA1Mi4xTDY2LjggMTgyLjZoMjEuN2wxMS43LTI5LjJoNDkuNGwxMS43IDI5LjJIMTgzTDEyNSA1Mi4xem0xNyA4My4zaC0zNGwxNy00MC45IDE3IDQwLjl6IiAvPgogIDwvc3ZnPg==">
</div>

<div class="container">
&nbsp; <router-outlet></router-outlet>
</div>

Open and edit src/app/app.component.scss then replace all SCSS codes with this.

.container {
&nbsp; padding: 20px;
}

11. Create Service for Accessing RESTful API

To access ASP.NET Core Web API from Angular 7 application, we have to create an Angular 7 Service first. Type this command to create it.

ng g service api

We have to register the HttpClient module before using it in the Service. Open and edit src/app/app.module.ts then add this import.

import { FormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';

Add them to the `@NgModule` imports array.

imports: [
&nbsp; BrowserModule,
&nbsp; FormsModule,
&nbsp; HttpClientModule,
&nbsp; AppRoutingModule
],

To specify the type of response object from the ASP.NET Core Web API, we have to create a class for it. Create a new file src/app/supplier.ts then add this codes.

export class Supplier {
&nbsp; &nbsp; supplierId: number;
&nbsp; &nbsp; companyName: string;
&nbsp; &nbsp; contactName: string;
&nbsp; &nbsp; contactTitle: string;
&nbsp; &nbsp; address: string;
&nbsp; &nbsp; city: string;
&nbsp; &nbsp; region: string;
&nbsp; &nbsp; postalCode: string;
&nbsp; &nbsp; country: string;
&nbsp; &nbsp; phone: string;
&nbsp; &nbsp; fax: string;
&nbsp; &nbsp; homePage: string;
}

Next, open and edit src/app/api.service.ts then add this imports.

import { Observable, of, throwError } from 'rxjs';
import { HttpClient, HttpHeaders, HttpErrorResponse } from '@angular/common/http';
import { catchError, tap, map } from 'rxjs/operators';
import { Supplier } from './supplier';

Add these constants before the @Injectable.

const httpOptions = {
&nbsp; headers: new HttpHeaders({'Content-Type': 'application/json'})
};
const apiUrl = 'http://localhost:5000/api/';

Inject HttpClient module to the constructor.

constructor(private http: HttpClient) { }

Add the error handler function.

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

&nbsp; &nbsp; // TODO: send the error to remote logging infrastructure
&nbsp; &nbsp; console.error(error); // log to console instead

&nbsp; &nbsp; // Let the app keep running by returning an empty result.
&nbsp; &nbsp; return of(result as T);
&nbsp; };
}

Add all CRUD (create, read, update, delete) functions of suppliers data.

getSuppliers (): Observable<Supplier[]> {
&nbsp; return this.http.get<Supplier[]>(apiUrl)
&nbsp; &nbsp; .pipe(
&nbsp; &nbsp; &nbsp; tap(heroes => console.log('fetched Suppliers')),
&nbsp; &nbsp; &nbsp; catchError(this.handleError('getSuppliers', []))
&nbsp; &nbsp; );
}

getSupplier(id: number): Observable<Supplier> {
&nbsp; const url = `${apiUrl}/${id}`;
&nbsp; return this.http.get<Supplier>(url).pipe(
&nbsp; &nbsp; tap(_ => console.log(`fetched Supplier id=${id}`)),
&nbsp; &nbsp; catchError(this.handleError<Supplier>(`getSupplier id=${id}`))
&nbsp; );
}

addSupplier (supplier: any): Observable<Supplier> {
&nbsp; return this.http.post<Supplier>(apiUrl, supplier, httpOptions).pipe(
&nbsp; &nbsp; tap((supplierRes: Supplier) => console.log(`added Supplier w/ id=${supplierRes.supplierId}`)),
&nbsp; &nbsp; catchError(this.handleError<Supplier>('addSupplier'))
&nbsp; );
}

updateSupplier (id: number, supplier: any): Observable<any> {
&nbsp; const url = `${apiUrl}/${id}`;
&nbsp; return this.http.put(url, supplier, httpOptions).pipe(
&nbsp; &nbsp; tap(_ => console.log(`updated Supplier id=${id}`)),
&nbsp; &nbsp; catchError(this.handleError<any>('updateSupplier'))
&nbsp; );
}

deleteSupplier (id: number): Observable<Supplier> {
&nbsp; const url = `${apiUrl}/${id}`;
&nbsp; return this.http.delete<Supplier>(url, httpOptions).pipe(
&nbsp; &nbsp; tap(_ => console.log(`deleted Supplier id=${id}`)),
&nbsp; &nbsp; catchError(this.handleError<Supplier>('deleteSupplier'))
&nbsp; );
}

12. Display List of Suppliers using Angular 7 Material

To display a list of suppliers to the Angular 7 template. First, open and edit src/app/supplier/supplier.component.ts then add this imports.

import { ApiService } from '../api.service';

Next, inject the API Service to the constructor.

constructor(private api: ApiService) { }

Next, for user interface (UI) we will use Angular 7 Material and CDK. There’s a CLI for generating a Material component like Table as a component, but we will create or add the Table component from scratch to existing component. Type this command to install Angular 7 Material.

ng add @angular/material

If there are some questions, answer them like below.

? Choose a prebuilt theme name, or "custom" for a custom theme: Purple/Green &nbsp; &nbsp; &nbsp; [ Preview: https://material.angular.i
o?theme=purple-green ]
? Set up HammerJS for gesture recognition? Yes
? Set up browser animations for Angular Material? Yes

Next, we have to register all required Angular Material components or modules to src/app/app.module.ts. Open and edit that file then add this imports.

import {
&nbsp; MatInputModule,
&nbsp; MatPaginatorModule,
&nbsp; MatProgressSpinnerModule,
&nbsp; MatSortModule,
&nbsp; MatTableModule,
&nbsp; MatIconModule,
&nbsp; MatButtonModule,
&nbsp; MatCardModule,
&nbsp; MatFormFieldModule } from '@angular/material';

Also, modify FormsModule import to add ReactiveFormsModule.

import { FormsModule, ReactiveFormsModule } from '@angular/forms';

Register the above modules to @NgModule imports.

imports: [
&nbsp; BrowserModule,
&nbsp; FormsModule,
&nbsp; HttpClientModule,
&nbsp; AppRoutingModule,
&nbsp; ReactiveFormsModule,
&nbsp; BrowserAnimationsModule,
&nbsp; MatInputModule,
&nbsp; MatTableModule,
&nbsp; MatPaginatorModule,
&nbsp; MatSortModule,
&nbsp; MatProgressSpinnerModule,
&nbsp; MatIconModule,
&nbsp; MatButtonModule,
&nbsp; MatCardModule,
&nbsp; MatFormFieldModule
],

Next, back to src/app/supplier/supplier.component.ts then add this imports.

import { Supplier } from '../supplier';

Declare the variables of Angular Material Table Data Source before the constructor.

displayedColumns: string[] = ['supplierId', 'companyName', 'contactName'];
data: Supplier[] = [];
isLoadingResults = true;

Modify the ngOnInit function to get list of suppliers immediately.

ngOnInit() {
&nbsp; this.api.getSuppliers()
&nbsp; .subscribe(res => {
&nbsp; &nbsp; this.data = res;
&nbsp; &nbsp; console.log(this.data);
&nbsp; &nbsp; this.isLoadingResults = false;
&nbsp; }, err => {
&nbsp; &nbsp; console.log(err);
&nbsp; &nbsp; this.isLoadingResults = false;
&nbsp; });
}

Next, open and edit src/app/supplier/supplier.component.html then replace all HTML tags with this Angular 7 Material tags.

<div class="example-container mat-elevation-z8">
&nbsp; <div class="example-loading-shade"
&nbsp; &nbsp; &nbsp; &nbsp;*ngIf="isLoadingResults">
&nbsp; &nbsp; <mat-spinner *ngIf="isLoadingResults"></mat-spinner>
&nbsp; </div>
&nbsp; <div class="button-row">
&nbsp; &nbsp; <a mat-flat-button color="primary" [routerLink]="['/supplier-add']"><mat-icon>add</mat-icon></a>
&nbsp; </div>
&nbsp; <div class="mat-elevation-z8">
&nbsp; &nbsp; <table mat-table [dataSource]="data" class="example-table"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;matSort matSortActive="CompanyName" matSortDisableClear matSortDirection="asc">

&nbsp; &nbsp; &nbsp; <!-- Supplier ID Column -->
&nbsp; &nbsp; &nbsp; <ng-container matColumnDef="supplierId">
&nbsp; &nbsp; &nbsp; &nbsp; <th mat-header-cell *matHeaderCellDef>Supplier ID</th>
&nbsp; &nbsp; &nbsp; &nbsp; <td mat-cell *matCellDef="let row">{{row.supplierId}}</td>
&nbsp; &nbsp; &nbsp; </ng-container>

&nbsp; &nbsp; &nbsp; <!-- Company Name Column -->
&nbsp; &nbsp; &nbsp; <ng-container matColumnDef="companyName">
&nbsp; &nbsp; &nbsp; &nbsp; <th mat-header-cell *matHeaderCellDef>Company Name</th>
&nbsp; &nbsp; &nbsp; &nbsp; <td mat-cell *matCellDef="let row">{{row.companyName}}</td>
&nbsp; &nbsp; &nbsp; </ng-container>

&nbsp; &nbsp; &nbsp; <!-- Contact Name Column -->
&nbsp; &nbsp; &nbsp; <ng-container matColumnDef="contactName">
&nbsp; &nbsp; &nbsp; &nbsp; <th mat-header-cell *matHeaderCellDef>Contact Name</th>
&nbsp; &nbsp; &nbsp; &nbsp; <td mat-cell *matCellDef="let row">{{row.contactName}}</td>
&nbsp; &nbsp; &nbsp; </ng-container>

&nbsp; &nbsp; &nbsp; <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
&nbsp; &nbsp; &nbsp; <tr mat-row *matRowDef="let row; columns: displayedColumns;" [routerLink]="['/supplier-details/', row.supplierId]"></tr>
&nbsp; &nbsp; </table>
&nbsp; </div>
</div>

Finally, to make a little UI adjustment, open and edit src/app/supplier/supplier.component.css then add this CSS codes.

/* Structure */
.example-container {
&nbsp; &nbsp; position: relative;
&nbsp; &nbsp; padding: 5px;
&nbsp; }

&nbsp; .example-table-container {
&nbsp; &nbsp; position: relative;
&nbsp; &nbsp; max-height: 400px;
&nbsp; &nbsp; overflow: auto;
&nbsp; }

&nbsp; table {
&nbsp; &nbsp; width: 100%;
&nbsp; }

&nbsp; .example-loading-shade {
&nbsp; &nbsp; position: absolute;
&nbsp; &nbsp; top: 0;
&nbsp; &nbsp; left: 0;
&nbsp; &nbsp; bottom: 56px;
&nbsp; &nbsp; right: 0;
&nbsp; &nbsp; background: rgba(0, 0, 0, 0.15);
&nbsp; &nbsp; z-index: 1;
&nbsp; &nbsp; display: flex;
&nbsp; &nbsp; align-items: center;
&nbsp; &nbsp; justify-content: center;
&nbsp; }

&nbsp; .example-rate-limit-reached {
&nbsp; &nbsp; color: #980000;
&nbsp; &nbsp; max-width: 360px;
&nbsp; &nbsp; text-align: center;
&nbsp; }

&nbsp; /* Column Widths */
&nbsp; .mat-column-number,
&nbsp; .mat-column-state {
&nbsp; &nbsp; max-width: 64px;
&nbsp; }

&nbsp; .mat-column-created {
&nbsp; &nbsp; max-width: 124px;
&nbsp; }

&nbsp; .mat-flat-button {
&nbsp; &nbsp; margin: 5px;
&nbsp; }

13. Show and Delete Supplier Details using Angular 7 Material

To show supplier details after click or tap on the one of a row inside the Angular 7 Material table, open and edit src/app/supplier-detail/supplier-detail.component.ts then add this imports.

import { ActivatedRoute, Router } from '@angular/router';
import { ApiService } from '../api.service';
import { Supplier } from '../supplier';

Inject above modules to the constructor.

constructor(private route: ActivatedRoute, private api: ApiService, private router: Router) { }

Declare the variables before the constructor for hold supplier data that get from the API.

supplier: Supplier = {
&nbsp; supplierId: null,
&nbsp; companyName: '',
&nbsp; contactName: '',
&nbsp; contactTitle: '',
&nbsp; address: '',
&nbsp; city: '',
&nbsp; region: '',
&nbsp; postalCode: '',
&nbsp; country: '',
&nbsp; phone: '',
&nbsp; fax: '',
&nbsp; homePage: ''
};
isLoadingResults = true;

Add a function for getting Supplier data from the API.

getSupplierDetails(id) {
&nbsp; this.api.getSupplier(id)
&nbsp; &nbsp; .subscribe(data => {
&nbsp; &nbsp; &nbsp; this.supplier = data;
&nbsp; &nbsp; &nbsp; console.log(this.supplier);
&nbsp; &nbsp; &nbsp; this.isLoadingResults = false;
&nbsp; &nbsp; });
}

Call that function when the component is initiated.

ngOnInit() {
&nbsp; this.getSupplierDetails(this.route.snapshot.params['id']);
}

Add this function for delete supplier.

deleteSupplier(id: number) {
&nbsp; this.isLoadingResults = true;
&nbsp; this.api.deleteSupplier(id)
&nbsp; &nbsp; .subscribe(res => {
&nbsp; &nbsp; &nbsp; &nbsp; this.isLoadingResults = false;
&nbsp; &nbsp; &nbsp; &nbsp; this.router.navigate(['/supplier']);
&nbsp; &nbsp; &nbsp; }, (err) => {
&nbsp; &nbsp; &nbsp; &nbsp; console.log(err);
&nbsp; &nbsp; &nbsp; &nbsp; this.isLoadingResults = false;
&nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; );
}

For the view, open and edit src/app/supplier-detail/supplier-detail.component.html then replace all HTML tags with this.

<div class="example-container mat-elevation-z8">
&nbsp; <div class="example-loading-shade"
&nbsp; &nbsp; &nbsp; &nbsp;*ngIf="isLoadingResults">
&nbsp; &nbsp; <mat-spinner *ngIf="isLoadingResults"></mat-spinner>
&nbsp; </div>
&nbsp; <div class="button-row">
&nbsp; &nbsp; <a mat-flat-button color="primary" [routerLink]="['/supplier']"><mat-icon>list</mat-icon></a>
&nbsp; </div>
&nbsp; <mat-card class="example-card">
&nbsp; &nbsp; <mat-card-header>
&nbsp; &nbsp; &nbsp; <mat-card-title><h2>Supplier ID: {{supplier.supplierId}}</h2></mat-card-title>
&nbsp; &nbsp; &nbsp; <mat-card-subtitle>Company Name: {{supplier.companyName}}</mat-card-subtitle>
&nbsp; &nbsp; </mat-card-header>
&nbsp; &nbsp; <mat-card-content>
&nbsp; &nbsp; &nbsp; <dl>
&nbsp; &nbsp; &nbsp; &nbsp; <dt>Contact Name:</dt>
&nbsp; &nbsp; &nbsp; &nbsp; <dd>{{supplier.contactName}}</dd>
&nbsp; &nbsp; &nbsp; &nbsp; <dt>Contact Title:</dt>
&nbsp; &nbsp; &nbsp; &nbsp; <dd>{{supplier.contactTitle}}</dd>
&nbsp; &nbsp; &nbsp; &nbsp; <dt>Address:</dt>
&nbsp; &nbsp; &nbsp; &nbsp; <dd>{{supplier.address}}</dd>
&nbsp; &nbsp; &nbsp; &nbsp; <dt>City:</dt>
&nbsp; &nbsp; &nbsp; &nbsp; <dd>{{supplier.city}}</dd>
&nbsp; &nbsp; &nbsp; &nbsp; <dt>Region:</dt>
&nbsp; &nbsp; &nbsp; &nbsp; <dd>{{supplier.region}}</dd>
&nbsp; &nbsp; &nbsp; &nbsp; <dt>Postal Code:</dt>
&nbsp; &nbsp; &nbsp; &nbsp; <dd>{{supplier.postalCode}}</dd>
&nbsp; &nbsp; &nbsp; &nbsp; <dt>Country:</dt>
&nbsp; &nbsp; &nbsp; &nbsp; <dd>{{supplier.country}}</dd>
&nbsp; &nbsp; &nbsp; &nbsp; <dt>Phone:</dt>
&nbsp; &nbsp; &nbsp; &nbsp; <dd>{{supplier.phone}}</dd>
&nbsp; &nbsp; &nbsp; &nbsp; <dt>Fax:</dt>
&nbsp; &nbsp; &nbsp; &nbsp; <dd>{{supplier.fax}}</dd>
&nbsp; &nbsp; &nbsp; &nbsp; <dt>Home Page:</dt>
&nbsp; &nbsp; &nbsp; &nbsp; <dd>{{supplier.homePage}}</dd>
&nbsp; &nbsp; &nbsp; </dl>
&nbsp; &nbsp; </mat-card-content>
&nbsp; &nbsp; <mat-card-actions>
&nbsp; &nbsp; &nbsp; <a mat-flat-button color="primary" [routerLink]="['/supplier-edit/', supplier.supplierId || 'all']"><mat-icon>edit</mat-icon></a>
&nbsp; &nbsp; &nbsp; <a mat-flat-button color="warn" (click)="deleteSupplier(supplier.supplierId)"><mat-icon>delete</mat-icon></a>
&nbsp; &nbsp; </mat-card-actions>
&nbsp; </mat-card>
</div>

Finally, open and edit src/app/supplier-detail/supplier-detail.component.css then add these lines of CSS codes.

/* Structure */
.example-container {
&nbsp; position: relative;
&nbsp; padding: 5px;
}

.example-loading-shade {
&nbsp; position: absolute;
&nbsp; top: 0;
&nbsp; left: 0;
&nbsp; bottom: 56px;
&nbsp; right: 0;
&nbsp; background: rgba(0, 0, 0, 0.15);
&nbsp; z-index: 1;
&nbsp; display: flex;
&nbsp; align-items: center;
&nbsp; justify-content: center;
}

.mat-flat-button {
&nbsp; margin: 5px;
}

14. Add a Supplier using Angular 7 Material

To add a new supplier, we have to create Angular 7 reactive form. Open and edit src/app/supplier-add/supplier-add.component.ts then add this imports.

import { Router } from '@angular/router';
import { ApiService } from '../api.service';
import { FormControl, FormGroupDirective, FormBuilder, FormGroup, NgForm, Validators } from '@angular/forms';

Inject above modules to the constructor.

constructor(private router: Router, private api: ApiService, private formBuilder: FormBuilder) { }

Declare variables for the Form Group and all of the required fields inside the form before the constructor.

supplierForm: FormGroup;
companyName = '';
contactName = '';
contactTitle = '';
address = '';
city = '';
region = '';
postalCode = '';
country = '';
phone = '';
fax = '';
homePage = '';
isLoadingResults = false;

Add initial validation for each field.

ngOnInit() {
&nbsp; this.supplierForm = this.formBuilder.group({
&nbsp; &nbsp; 'companyName' : [null, Validators.required],
&nbsp; &nbsp; 'contactName' : [null, null],
&nbsp; &nbsp; 'contactTitle' : [null, null],
&nbsp; &nbsp; 'address' : [null, null],
&nbsp; &nbsp; 'city' : [null, null],
&nbsp; &nbsp; 'region' : [null, null],
&nbsp; &nbsp; 'postalCode' : [null, null],
&nbsp; &nbsp; 'country' : [null, null],
&nbsp; &nbsp; 'phone' : [null, null],
&nbsp; &nbsp; 'fax' : [null, null],
&nbsp; &nbsp; 'homePage' : [null, null]
&nbsp; });
}

Create a function for submitting or POST supplier form.

onFormSubmit(form: NgForm) {
&nbsp; this.isLoadingResults = true;
&nbsp; this.api.addSupplier(form)
&nbsp; &nbsp; .subscribe((res: { [x: string]: any; }) => {
&nbsp; &nbsp; &nbsp; &nbsp; const supplier = res['supplierResponse'];
&nbsp; &nbsp; &nbsp; &nbsp; const id = supplier['supplierId'];
&nbsp; &nbsp; &nbsp; &nbsp; this.isLoadingResults = false;
&nbsp; &nbsp; &nbsp; &nbsp; this.router.navigate(['/supplier-details', id]);
&nbsp; &nbsp; &nbsp; }, (err) => {
&nbsp; &nbsp; &nbsp; &nbsp; console.log(err);
&nbsp; &nbsp; &nbsp; &nbsp; this.isLoadingResults = false;
&nbsp; &nbsp; &nbsp; });
}

Next, add this import for implementing ErrorStateMatcher.

import { ErrorStateMatcher } from '@angular/material/core';

Create a new class after the end of this class bracket.

/** Error when invalid control is dirty, touched, or submitted. */
export class MyErrorStateMatcher implements ErrorStateMatcher {
&nbsp; isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
&nbsp; &nbsp; const isSubmitted = form && form.submitted;
&nbsp; &nbsp; return !!(control && control.invalid && (control.dirty || control.touched || isSubmitted));
&nbsp; }
}

Instantiate that MyErrorStateMatcher as a variable in main class.

matcher = new MyErrorStateMatcher();

Next, open and edit src/app/supplier-add/supplier-add.component.html then replace all HTML tags with this.

<div class="example-container mat-elevation-z8">
&nbsp; <div class="example-loading-shade"
&nbsp; &nbsp; &nbsp; &nbsp;*ngIf="isLoadingResults">
&nbsp; &nbsp; <mat-spinner *ngIf="isLoadingResults"></mat-spinner>
&nbsp; </div>
&nbsp; <div class="button-row">
&nbsp; &nbsp; <a mat-flat-button color="primary" [routerLink]="['/supplier']"><mat-icon>list</mat-icon></a>
&nbsp; </div>
&nbsp; <mat-card class="example-card">
&nbsp; &nbsp; <form [formGroup]="supplierForm" (ngSubmit)="onFormSubmit(supplierForm.value)">
&nbsp; &nbsp; &nbsp; <mat-form-field class="example-full-width">
&nbsp; &nbsp; &nbsp; &nbsp; <input matInput placeholder="Company Name" formControlName="companyName"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[errorStateMatcher]="matcher">
&nbsp; &nbsp; &nbsp; &nbsp; <mat-error>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span *ngIf="!supplierForm.get('companyName').valid && supplierForm.get('companyName').touched">Please enter Company Name</span>
&nbsp; &nbsp; &nbsp; &nbsp; </mat-error>
&nbsp; &nbsp; &nbsp; </mat-form-field>
&nbsp; &nbsp; &nbsp; <mat-form-field class="example-full-width">
&nbsp; &nbsp; &nbsp; &nbsp; <input matInput placeholder="Contact Name" formControlName="contactName"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[errorStateMatcher]="matcher">
&nbsp; &nbsp; &nbsp; </mat-form-field>
&nbsp; &nbsp; &nbsp; <mat-form-field class="example-full-width">
&nbsp; &nbsp; &nbsp; &nbsp; <input matInput placeholder="Contact Title" formControlName="contactTitle"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[errorStateMatcher]="matcher">
&nbsp; &nbsp; &nbsp; </mat-form-field>
&nbsp; &nbsp; &nbsp; <mat-form-field class="example-full-width">
&nbsp; &nbsp; &nbsp; &nbsp; <input matInput placeholder="Address" formControlName="address"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[errorStateMatcher]="matcher">
&nbsp; &nbsp; &nbsp; </mat-form-field>
&nbsp; &nbsp; &nbsp; <mat-form-field class="example-full-width">
&nbsp; &nbsp; &nbsp; &nbsp; <input matInput placeholder="City" formControlName="city"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[errorStateMatcher]="matcher">
&nbsp; &nbsp; &nbsp; </mat-form-field>
&nbsp; &nbsp; &nbsp; <mat-form-field class="example-full-width">
&nbsp; &nbsp; &nbsp; &nbsp; <input matInput placeholder="Region" formControlName="region"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[errorStateMatcher]="matcher">
&nbsp; &nbsp; &nbsp; </mat-form-field>
&nbsp; &nbsp; &nbsp; <mat-form-field class="example-full-width">
&nbsp; &nbsp; &nbsp; &nbsp; <input matInput placeholder="Postal Code" formControlName="postalCode"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[errorStateMatcher]="matcher">
&nbsp; &nbsp; &nbsp; </mat-form-field>
&nbsp; &nbsp; &nbsp; <mat-form-field class="example-full-width">
&nbsp; &nbsp; &nbsp; &nbsp; <input matInput placeholder="Country" formControlName="country"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[errorStateMatcher]="matcher">
&nbsp; &nbsp; &nbsp; </mat-form-field>
&nbsp; &nbsp; &nbsp; <mat-form-field class="example-full-width">
&nbsp; &nbsp; &nbsp; &nbsp; <input matInput placeholder="Phone" formControlName="phone"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[errorStateMatcher]="matcher">
&nbsp; &nbsp; &nbsp; </mat-form-field>
&nbsp; &nbsp; &nbsp; <mat-form-field class="example-full-width">
&nbsp; &nbsp; &nbsp; &nbsp; <input matInput placeholder="Fax" formControlName="fax"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[errorStateMatcher]="matcher">
&nbsp; &nbsp; &nbsp; </mat-form-field>
&nbsp; &nbsp; &nbsp; <mat-form-field class="example-full-width">
&nbsp; &nbsp; &nbsp; &nbsp; <input matInput placeholder="Home Page" formControlName="homePage"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[errorStateMatcher]="matcher">
&nbsp; &nbsp; &nbsp; </mat-form-field>
&nbsp; &nbsp; &nbsp; <div class="button-row">
&nbsp; &nbsp; &nbsp; &nbsp; <button type="submit" [disabled]="!supplierForm.valid" mat-flat-button color="primary"><mat-icon>save</mat-icon></button>
&nbsp; &nbsp; &nbsp; </div>
&nbsp; &nbsp; </form>
&nbsp; </mat-card>
</div>

Finally, open and edit src/app/supplier-add/supplier-add.component.css then add this CSS codes.

/* Structure */
.example-container {
&nbsp; position: relative;
&nbsp; padding: 5px;
}

.example-form {
&nbsp; min-width: 150px;
&nbsp; max-width: 500px;
&nbsp; width: 100%;
}

.example-full-width {
&nbsp; width: 100%;
}

.example-full-width:nth-last-child() {
&nbsp; margin-bottom: 10px;
}

.button-row {
&nbsp; margin: 10px 0;
}

.mat-flat-button {
&nbsp; margin: 5px;
}

15. Edit a Supplier using Angular 7 Material

We have put an edit button inside the Supplier Detail component for call Edit page. Now, open and edit src/app/supplier-edit/supplier-edit.component.ts then add this imports.

import { Router, ActivatedRoute } from '@angular/router';
import { ApiService } from '../api.service';
import { FormControl, FormGroupDirective, FormBuilder, FormGroup, NgForm, Validators } from '@angular/forms';
import { ErrorStateMatcher } from '@angular/material/core';

Inject above modules to the constructor.

constructor(private router: Router, private route: ActivatedRoute, private api: ApiService, private formBuilder: FormBuilder) { }

Declare the Form Group variable and all of the required variables for the supplier form before the constructor.

supplierForm: FormGroup;
companyName = '';
contactName = '';
contactTitle = '';
address = '';
city = '';
region = '';
postalCode = '';
country = '';
phone = '';
fax = '';
homePage = '';
isLoadingResults = false;
matcher = new MyErrorStateMatcher();

Next, add validation for all fields when the component is initiated.

ngOnInit() {
&nbsp; this.getSupplier(this.route.snapshot.params['id']);
&nbsp; this.supplierForm = this.formBuilder.group({
&nbsp; &nbsp; 'companyName' : [null, Validators.required],
&nbsp; &nbsp; 'contactName' : [null, null],
&nbsp; &nbsp; 'contactTitle' : [null, null],
&nbsp; &nbsp; 'address' : [null, null],
&nbsp; &nbsp; 'city' : [null, null],
&nbsp; &nbsp; 'region' : [null, null],
&nbsp; &nbsp; 'postalCode' : [null, null],
&nbsp; &nbsp; 'country' : [null, null],
&nbsp; &nbsp; 'phone' : [null, null],
&nbsp; &nbsp; 'fax' : [null, null],
&nbsp; &nbsp; 'homePage' : [null, null]
&nbsp; });
}

Create a function for getting supplier data that filled to each form fields.

getSupplier(id: number) {
&nbsp; this.api.getSupplier(id).subscribe(data => {
&nbsp; &nbsp; this.supplierId = data.supplierId;
&nbsp; &nbsp; this.supplierForm.setValue({
&nbsp; &nbsp; &nbsp; companyName: data.companyName,
&nbsp; &nbsp; &nbsp; contactName: data.contactName,
&nbsp; &nbsp; &nbsp; contactTitle: data.contactTitle,
&nbsp; &nbsp; &nbsp; address: data.address,
&nbsp; &nbsp; &nbsp; city: data.city,
&nbsp; &nbsp; &nbsp; region: data.region,
&nbsp; &nbsp; &nbsp; postalCode: data.postalCode,
&nbsp; &nbsp; &nbsp; country: data.country,
&nbsp; &nbsp; &nbsp; phone: data.phone,
&nbsp; &nbsp; &nbsp; fax: data.fax,
&nbsp; &nbsp; &nbsp; homePage: data.homePage
&nbsp; &nbsp; });
&nbsp; });
}

Create a function to update the supplier changes.

onFormSubmit(form: NgForm) {
&nbsp; this.isLoadingResults = true;
&nbsp; this.api.updateSupplier(this.supplierId, form)
&nbsp; &nbsp; .subscribe(res => {
&nbsp; &nbsp; &nbsp; &nbsp; this.isLoadingResults = false;
&nbsp; &nbsp; &nbsp; &nbsp; this.router.navigate(['/supplier']);
&nbsp; &nbsp; &nbsp; }, (err) => {
&nbsp; &nbsp; &nbsp; &nbsp; console.log(err);
&nbsp; &nbsp; &nbsp; &nbsp; this.isLoadingResults = false;
&nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; );
}

Add a function for handling show supplier details button.

supplierDetails() {
&nbsp; this.router.navigate(['/supplier-details', this.supplierId]);
}

Add a class that implementing ErrorStateMatcher after the current class.

/** Error when invalid control is dirty, touched, or submitted. */
export class MyErrorStateMatcher implements ErrorStateMatcher {
&nbsp; isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
&nbsp; &nbsp; const isSubmitted = form && form.submitted;
&nbsp; &nbsp; return !!(control && control.invalid && (control.dirty || control.touched || isSubmitted));
&nbsp; }
}

Next, open and edit src/app/supplier-edit/supplier-edit.component.html then replace all HTML tags with this.

<div class="example-container mat-elevation-z8">
&nbsp; <div class="example-loading-shade"
&nbsp; &nbsp; &nbsp; &nbsp;*ngIf="isLoadingResults">
&nbsp; &nbsp; <mat-spinner *ngIf="isLoadingResults"></mat-spinner>
&nbsp; </div>
&nbsp; <div class="button-row">
&nbsp; &nbsp; <a mat-flat-button color="primary" [routerLink]="['/supplier']"><mat-icon>list</mat-icon></a>
&nbsp; </div>
&nbsp; <mat-card class="example-card">
&nbsp; &nbsp; <form [formGroup]="supplierForm" (ngSubmit)="onFormSubmit(supplierForm.value)">
&nbsp; &nbsp; &nbsp; <mat-form-field class="example-full-width">
&nbsp; &nbsp; &nbsp; &nbsp; <input matInput placeholder="Company Name" formControlName="companyName"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[errorStateMatcher]="matcher">
&nbsp; &nbsp; &nbsp; &nbsp; <mat-error>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span *ngIf="!supplierForm.get('companyName').valid && supplierForm.get('companyName').touched">Please enter Company Name</span>
&nbsp; &nbsp; &nbsp; &nbsp; </mat-error>
&nbsp; &nbsp; &nbsp; </mat-form-field>
&nbsp; &nbsp; &nbsp; <mat-form-field class="example-full-width">
&nbsp; &nbsp; &nbsp; &nbsp; <input matInput placeholder="Contact Name" formControlName="contactName"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[errorStateMatcher]="matcher">
&nbsp; &nbsp; &nbsp; </mat-form-field>
&nbsp; &nbsp; &nbsp; <mat-form-field class="example-full-width">
&nbsp; &nbsp; &nbsp; &nbsp; <input matInput placeholder="Contact Title" formControlName="contactTitle"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[errorStateMatcher]="matcher">
&nbsp; &nbsp; &nbsp; </mat-form-field>
&nbsp; &nbsp; &nbsp; <mat-form-field class="example-full-width">
&nbsp; &nbsp; &nbsp; &nbsp; <input matInput placeholder="Address" formControlName="address"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[errorStateMatcher]="matcher">
&nbsp; &nbsp; &nbsp; </mat-form-field>
&nbsp; &nbsp; &nbsp; <mat-form-field class="example-full-width">
&nbsp; &nbsp; &nbsp; &nbsp; <input matInput placeholder="City" formControlName="city"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[errorStateMatcher]="matcher">
&nbsp; &nbsp; &nbsp; </mat-form-field>
&nbsp; &nbsp; &nbsp; <mat-form-field class="example-full-width">
&nbsp; &nbsp; &nbsp; &nbsp; <input matInput placeholder="Region" formControlName="region"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[errorStateMatcher]="matcher">
&nbsp; &nbsp; &nbsp; </mat-form-field>
&nbsp; &nbsp; &nbsp; <mat-form-field class="example-full-width">
&nbsp; &nbsp; &nbsp; &nbsp; <input matInput placeholder="Postal Code" formControlName="postalCode"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[errorStateMatcher]="matcher">
&nbsp; &nbsp; &nbsp; </mat-form-field>
&nbsp; &nbsp; &nbsp; <mat-form-field class="example-full-width">
&nbsp; &nbsp; &nbsp; &nbsp; <input matInput placeholder="Country" formControlName="country"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[errorStateMatcher]="matcher">
&nbsp; &nbsp; &nbsp; </mat-form-field>
&nbsp; &nbsp; &nbsp; <mat-form-field class="example-full-width">
&nbsp; &nbsp; &nbsp; &nbsp; <input matInput placeholder="Phone" formControlName="phone"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[errorStateMatcher]="matcher">
&nbsp; &nbsp; &nbsp; </mat-form-field>
&nbsp; &nbsp; &nbsp; <mat-form-field class="example-full-width">
&nbsp; &nbsp; &nbsp; &nbsp; <input matInput placeholder="Fax" formControlName="fax"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[errorStateMatcher]="matcher">
&nbsp; &nbsp; &nbsp; </mat-form-field>
&nbsp; &nbsp; &nbsp; <mat-form-field class="example-full-width">
&nbsp; &nbsp; &nbsp; &nbsp; <input matInput placeholder="Home Page" formControlName="homePage"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;[errorStateMatcher]="matcher">
&nbsp; &nbsp; &nbsp; </mat-form-field>
&nbsp; &nbsp; &nbsp; <div class="button-row">
&nbsp; &nbsp; &nbsp; &nbsp; <button type="submit" [disabled]="!supplierForm.valid" mat-flat-button color="primary"><mat-icon>update</mat-icon></button>
&nbsp; &nbsp; &nbsp; </div>
&nbsp; &nbsp; </form>
&nbsp; </mat-card>
</div>

Finally, open and edit src/app/supplier-edit/supplier-edit.component.css then add this lines of CSS codes.

/* Structure */
.example-container {
&nbsp; position: relative;
&nbsp; padding: 5px;
}

.example-form {
&nbsp; min-width: 150px;
&nbsp; max-width: 500px;
&nbsp; width: 100%;
}

.example-full-width {
&nbsp; width: 100%;
}

.example-full-width:nth-last-child() {
&nbsp; margin-bottom: 10px;
}

.button-row {
&nbsp; margin: 10px 0;
}

.mat-flat-button {
&nbsp; margin: 5px;
}

16. Run and Test the ASP.NET Core Web API and Angular 7 CRUD Web Application

Before running the ASP.NET Core Web API that consumes by Angular 7 application, make sure ASP.NET Core Web API serve by HTTP only. Just open Properties\launchSettings.json then remove https from the applicationUrl. Next, type this command in the Visual Studio Code Terminal.

dotnet watch run

To run the Angular 7 application, type this command from the Node.js Command Prompt.

ng serve

Now, you will see this Angular 7 pages when pointing your browser to localhost:4200.

You can just navigate through the whole Angular 7 application.

That it’s, the tutorial of Building Web App using ASP.NET Web API Angular 7 and SQL Server. You can find the fully working source code from our GitHub.

Learn More

Angular 7 (formerly Angular 2) - The Complete Guide

Learn and Understand AngularJS

Angular Crash Course for Busy Developers

The Complete Angular Course: Beginner to Advanced

Angular (Angular 2+) & NodeJS - The MEAN Stack Guide

The Complete ASP.NET MVC 5 Course

Build a Real-world App with ASP.NET Core and Angular 2 (4+)

ASP NET Core (ASP.NET 5),MVC 6,C#,Angular2 & EF Crash Course

#angular #asp.net #sql-server