Monday, August 12, 2019

How to use HttpClient Service in Angular 4 with Web API in Asp.Net MVC 4: C# and Vb.Net


First, we’ll create a table in SQL server and add few rows of data to it.

Create SQL Table dbo.Books

CREATE TABLE [dbo].[Books](
    [BookID] [int] IDENTITY(1,1) NOT NULL,
    [BookName] [varchar](50) NULL,
    [Category] [varchar](50) NULL,
    [Price] [numeric](18, 2) NULL,
    PRIMARY KEY CLUSTERED ( [BookID] ASC )
) ON [PRIMARY]
Add data to the table.
Web API (MVC 4)
You should have MVC 4 in Asp.Net installed in your computer.
Model Books.cs (C#)
using System;

namespace BooksApp.Models
{
    public class Books
    {
        public int BookID { get; set; }
        public string BookName { get; set; }
        public string Category { get; set; }
        public decimal Price { get; set; }
    }
}
Model Books.vb (Vb.Net)
Imports System.Web

Namespace BooksApp.Models
    Public Class Books
        Public Property BookName() As String
            Get
                Return m_BookName
            End Get
            Set(value As String)
                m_BookName = value
            End Set
        End Property
        Private m_BookName As String

        Public Property BookID() As String
            Get
                Return m_BookID
            End Get
            Set(value As String)
                m_BookID = value
            End Set
        End Property
        Private m_BookID As String

        Public Property Category() As String
            Get
                Return m_Category
            End Get
            Set(value As String)
                m_Category = value
            End Set
        End Property
        Private m_Category As String

        Public Property Price() As Decimal
            Get
                Return m_Price
            End Get
            Set(value As Decimal)
                m_Price = value
            End Set
        End Property
        Private m_Price As Decimal
    End Class
End Namespace

Web API Controller

The Controller in this project has a single public method called Get(), which will handle the http request and return the list of books to the calling application.
BooksController.cs (C#)
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.http;
using System.Web.http;

using BooksApp.Models;
using System.Data.SqlClient;

namespace BooksApp.Controllers
{
    public class BooksController : ApiController
    {

        // LIST OBJECT WILL HOLD AND RETURN A LIST OF BOOKS.
        List<Books> MyBooks = new List<Books>();

        // THE "GET" METHOD WILL RETURN ALL THE BOOKS IN THE TABLE.
        public IEnumerable<Books> Get()
        {
            string sConnString = "Data Source=DNA;Persist Security Info=False;" +
                "Initial Catalog=DNA_Classified;User Id=sa;Password=;Connect Timeout=30;";

            SqlConnection myConn = new SqlConnection(sConnString);

            // THE SQL QUERY TO GET THE BOOKS FROM THE TABLE.
            SqlCommand objComm = new SqlCommand("SELECT *FROM dbo.Books”, myConn);
            myConn.Open();

            SqlDataReader reader = objComm.ExecuteReader();

            // POPULATE THE LIST WITH DATA.
            while (reader.Read())
            {
                MyBooks.Add(new Books
                {
                    BookID = Convert.ToInt32(reader["BookID"]),
                    BookName = reader["BookName"].ToString(),
                    Category = reader["Category"].ToString(),
                    Price = Convert.ToDecimal(reader["Price"])
                });
            }
            myConn.Close();

            return MyBooks;
        }
    }
}
BooksController.vb (Vb.Net)
Option Explicit On

Imports System.Net.http
Imports System.Web.http

Imports System.Data.SqlClient
Imports BooksApp.BooksApp.Models

Namespace BooksApp
    Public Class BooksController
        Inherits ApiController

        ' LIST OBJECT WILL HOLD AND RETURN A LIST OF BOOKS.
        Dim MyBooks As New List(Of Books)()

        ' THE "GET" METHOD WILL RETURN ALL THE BOOKS IN THE TABLE.

        Public Function [Get]() As IEnumerable(Of Books)
            Dim sConnString As String = "Data Source=DNA;Persist Security Info=False;" & _
                "Initial Catalog=DNA_Classified;User Id=sa;Password=;Connect Timeout=30;"

            Dim myConn As New SqlConnection(sConnString)

            ' THE SQL QUERY TO GET THE BOOKS FROM THE TABLE.
            Dim objComm As New SqlCommand("SELECT * FROM dbo.Books", myConn)

            myConn.Open()

            Dim reader As SqlDataReader = objComm.ExecuteReader()

            ' POPULATE THE LIST WITH DATA.
            While reader.Read()
                MyBooks.Add(New Books() With { _
                    .BookID = CInt(reader("BookID")), _
                    .BookName = reader("BookName").ToString(), _
                    .Category = reader("Category").ToString(), _
                    .Price = CDbl(reader("Price")) _
                 })
            End While

            myConn.Close()

            Return MyBooks          ' FINALLY, RETURN THE LIST.
        End Function
    End Class
End Namespace
Once you have created the API, run the application. Don’t close it.

Create Angular 4 Project

Open the cmd prompt and go to the folder where you want to create the project and type,
ng new angular-with-webapi
Once the project is created, go to the folder.
cd angular-with-webapi
Launch the Server
Launch the server to check if everything is installed properly.
ng serve --open

Import HttpClientModule to the Project

You’ll have to import HttpClientModule in your project to access HttpClient services. Therefore, open app.module.ts file under src/app/ folder inside your project folder.
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { HttpClientModule } from '@angular/common/https';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
After you have imported HttpClientModule, you can now import HttpClient service to your components.

Create HttpClient Component to Request Data from API

Open app.component.ts file and copy and paste the code into it.
import { Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/https';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'Angular 4 with Web API';

  constructor (private httpService: HttpClient) { }
  myBooks: string [];

  ngOnInit () {
    this.httpService.get('http://localhost:43487/api/books/').subscribe(
      data => {
        this.myBooks = data as string [];
      }
    );
  }
}
After you have saved the data, it will automatically refresh the browser, where your app is running. Remember, you have launched the server.
Note: Check your browser console for any errors. A common error that occurs while working with Web API’s running on a different port is Error: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.
Please check this post to resolve the above-mentioned error. You’ll have to configure the Global.asax file in your Asp.Net Web API and run API application again.

What Am I Doing?

I have injected HttpClient into a constructor class. I am also using the get() method to make a request for data to the Web API.
The get() method has a URL (a different port) pointing to the API.
this.httpService.get('http://localhost:43487/api/books/')
Next, I have declared an array named myBooks of type string. I’ll store the data (provided by the API) into this array.
See how I am using the subscribe() method with a callback method named data =>.
To check if the API is responding to our request, add the console.log() method inside the callback method and check the browser console for results.
data => {
    console.log (data);
    // OR
    console.log (data[0].BookName);
}
If it has received data from the API, we’ll now add the data to the array, to display the result in our application template.
this.myBooks = data as string [];
The Template
The template is our markup where we attach the component properties to an element. This is where we’ll view the data we received through our Web API. I have stored the data in an Array in the component class. I wish to view the data in an HTML table. This is simple. You can also populate the data into a Dropdown list etc.
Open app.commponent.html file. Copy the below code into the file.
<div style="text-align:center;width:500px;">
    <h1> {{title}}! </h1>

    <div style="float:left;padding:10px;margin:0 auto;" *ngIf="myBooks">
        <table>
            <tr>
                <th>Book ID</th>
                    <th>Book Name</th>
                        <th>Category</th>
                            <th>Price</th>
            </tr>
            <tr *ngFor="let books of myBooks">    <!-- LOOP -->
                <td>{{books.BookID}}</td>
                    <td>{{books.BookName}}</td>
                        <td>{{books.Category}}</td>
                            <td>{{books.Price}}</td>
            </tr>
        </table>
    </div>
</div>
I have a <div> element, serving as a container. I am using *ngIf condition to check the array myBooks. Next, I have <table> element with header and rows using <tr>. The <tr> element is running a loop using *ngFor, which extracts data from the array myBooks and displays.
You can try using other elements, such as <ul> and <li>. For example,
<ul *ngFor="let books of myBooks">
    <li>{{ books.BookName + ' - ' + books.Price }}</li>
</ul>

Add Style to the Template

You can add little style to the <table> elements. Open app.components.css file and add the below CSS to it.
th, td {
    font:14px Verdana;
}
table, th, td {
    border:solid 1px #999;
    padding:2px 3px;
    text-align:center;
}
th {
    font-weight:bold;
}
You may add inline CSS too.
Save the files. It will automatically refresh the browser and if everyone is correct, you will see the extracted data on your browser.

No comments:

Post a Comment

No String Argument Constructor/Factory Method to Deserialize From String Value

  In this short article, we will cover in-depth the   JsonMappingException: no String-argument constructor/factory method to deserialize fro...