The new HttpClientModule is in @angular/common/https package. If you have created an Angular project before, you can check the @angular/common dependency in the package.json file.
Check this post if you are a beginner and haven’t setup Angular 4
Now let’s get started.
I have data in my SQL server database. I’ll make an http request using my Angular app to a Web API controller method, which will access data from an SQL server table and return the data (a List) to the requesting client (my Angular app). I’ll then bind the data to an HTML table in my project template.
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.
You should have MVC 4 in Asp.Net installed in your computer.
Note: If you are new to Web API, then please see this post. Its a step-by-step guide to Web Api.
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; } } }
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.
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; } } }
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 Project
Check this post if you are a beginner and haven’t setup Angular yet.
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 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 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 I have done here?
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 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.
Output
Error Handling in Angular
You will get errors while making http request. Possible scenarios, your Web API has stopped running or the API (after few updates) got errors. You can handle the errors in your Angular application.
Remember we have added a subscribe() method in our component. Open app.component.ts file and check the method. It has a callback method named data =>. You can add an error handler method as the second callback method like this.
import { HttpErrorResponse } from '@angular/common/https/src/response'; data => { this.myBooks = data as string []; }, (err: HttpErrorResponse) => { console.log (err.message); }
First, import HttpErrorResponse class to the component and add the err:HttpErrorResponse callback method, after the data=> method, separated by a comma. This will show error a message (if any) in your browser console.