Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / AngularJs

Build DotnetcoreAPIAngular6UI for Beginners

0.00/5 (No votes)
6 Feb 2019CPOL6 min read 4.7K  
How to build DotnetcoreAPIAngular6UI for beginners

Introduction

This article aims to provide beginners with guidelines to develop .NET Core web API and Angular 6 UI. This includes JWT, Swagger, Log4net, Middleware Configuration for Web API. Angular UI has Components, Routing, Services. This also provides few tips for developers who have a background of C# & JQuery to familiarize with Angular4/5/6 and make their hands dirty.

Project Development

Create New Project in VS2017, ASP.NET Core Web Application >> API, name as “CustService”.

Install the following packages:

  • Microsoft.EntityFrameworkCore.Design
  • Microsoft.EntityFrameworkCore.SqlServer
  • Microsoft.EntityFrameworkCore.SqlServer.Design

Create Folder Models and Service.

Execute the following command from Package Manager console to generate DBContext and Models.

Scaffold-DbContext "Server=DataSource;Database=CustomerDB;Trusted_Connection=True;" 
Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models

This creates CustomerDBContext, Customer, UserLogin Class files in Models folder.

Comment method in context file protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder).

Create ICustomerService, IAdminService add required functions for CRUD operations.

Create CustomerService, AdminService inherits from ICustomerService, IAdminservice and implements all methods of interface. In this Service, inject CustomerDBContext in constructor.

Add CustomerController, AdminController and create Actions for endpoints. Since there is no much business logic involved, each service has one Http* action.

Configuring

Add ConnectionStrings(DefaultConnection) in appsettings.json file.

In Startup.cs File

In ConfigureServices function, add the following lines:

C#
//DI for Services
services.AddScoped<ICustomerService, CustomerService>();
//DI for DBContext
services.AddScoped<CustomerDBContext>();
//Getting connection String from appsettings.json and add to context.
services.AddDbContext<CustomerDBContext>
(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

Swagger Configuration

Install Packages Swashbuckle.AspNetCore, Swashbuckle.AspNetCore.SwaggerUI to configure Swagger and to test APIs.

Add in the ConfigureServices method:

C#
services.AddSwaggerGen(c =>
     {
         c.SwaggerDoc("v1", new Info { Title = "Customer API", Version = "v1" });
     });

Add in the Configure method:

C#
// Enable middleware to serve generated Swagger as a JSON endpoint.
app.UseSwagger();

// Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.),
// specifying the Swagger JSON endpoint.
app.UseSwaggerUI(c =>
{
    c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
});

Log Configuration

Install Package Microsoft.Extensions.Logging.Log4Net.AspNetCore.

Add file log4net.config, which has configuration details for logging.

Add to Configure method:

C#
//bind from log4net.config xml file
loggerFactory.AddLog4Net();

<ItemGroup>
   <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.9" />
   <PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.1.3" />
   <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.1.3" />
   <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="2.1.3" />
   <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer.Design" Version="1.1.6" />
   <PackageReference Include="Microsoft.Extensions.Logging.Log4Net.AspNetCore" Version="2.2.10" />
   <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.0.4" />
   <PackageReference Include="Swashbuckle.AspNetCore" Version="4.0.1" />
   <PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="4.0.1" />
 </ItemGroup>

Implement JWT Security API

CustomerController actions are secured with JWT using [Authorize] attribute. Admincontroller has only one Action authenticate User which allows anonymous users, without login. [AllowAnonymous] attribute can be used for anonymous access.

JWT App Settings

The AppSettings class contains properties defined in appsettings.json.

Secret can be any GUID or string.

JavaScript
"AppSettings": {
       "Secret": "1eff8d6a-360f-48d2-a115-91f1cc2ece5d"
   }

Configure appsettings in Startup.cs, in ConfigureServices.

JavaScript
// configure strongly typed settings objects
var appSettingsSection = Configuration.GetSection("AppSettings");
services.Configure<AppSettings>(appSettingsSection);

Mapping of configuration sections is done in the ConfigureServices method of the Startup.cs file. Region JWTConfig.

Run the application and navigate to URL http://localhost:5327/swagger/index.html

User Authentication

AdminService contains Authenticate method which accepts Username, and Password as params to validate user against Table UserLogin.

On successful authentication, it generates a JWT (JSON Web Token) using the JwtSecurityTokenHandler class which is digitally signed using a secret key stored in appsettings.json. The JWT token is returned to the client application which has to be included in HTTP Authorization header of to access [Authorize] APIs.

Configure JWT for Swagger in Startup.cs, ConfigureServices method:

JavaScript
// Swagger 2.+ support
               var security = new Dictionary<string, IEnumerable<string>>
               {
                   {"Bearer", new string[] { }},
               };
 
               c.AddSecurityDefinition("Bearer", new ApiKeyScheme
               {
                   Description = "JWT Authorization header using the Bearer scheme. 
                            Example: \"Authorization: Bearer {token}\"",
                   Name = "Authorization",
                   In = "header",
                   Type = "apiKey"
               });
               c.AddSecurityRequirement(security);

Now Let Us Test Our APIs in Swagger

Run the application and launch URL http://localhost:5327/swagger/index.html.

Image 1

Create and sample record in Database table UserLogin, with username=”testing” and password=”testing”.

Click on /api/Admin/authenticate, “Try It Out”.

Enter valid username and password in userParam and Execute. Response with status “200” and “token” in Response Body.

Image 2

Copy the Token, which is used to test [Authorized] APIs.

Click on “Authorize” button and enter “Bearer“ past Token. It looks like the following. Click on Authorize button. For subsequent API calls from Swagger, this Bearer token will be added in header for Authorization.

Image 3

Create customer from Swagger with the required information, not to Enter CustID which is Identity Column.

Try testing “GetAllCustomer” API, so customers are created successfully.

Development of sample Web API has been completed.

Now We Can Start Developing UI in Angular6

Install Angular CLI and verify version "ng --v"

Angular CLI: 6.1.4

Node: 8.11.4

...and other packages installed.

Create Customer UI command: "ng new CustomerUI"

It may take some time to install all packages.

Run the following command for routing Module: for Navigation from List to Create Customer.

ng generate module app-routing --flat --module=app
//Display all Customers
ng g component CustomerList
//Display Customer Details and to add New Customer.
ng g component CustomerDetail
//Login page 
Ng g component login
//generate customer class

This application has 2 Models, Customer and UserLogin. Create 2 classes and 2 services to communicate with API.

//generate classes
ng g class customer
Ng g class userlogin
Ng g service customerservice
Ng g service userlogin

After creation of required components and Class and service Studio, the code looks as follows:

Image 4

Here, I would like to give some tips for new Angular 4/6 developers who are from Dotnet, Angularjs background. This may not be so accurate or helpful for beginners.

Functionality Angular 4/6 Dotnet
view .html aspx
code file .ts .aspx..cs
adding namespace import { FormBuilder, FormGroup, Validators } from '@angular/forms'; using Syste.*
coding language typescript C#
new page ng generate component.
Adds name*.component.html, component.ts, component.css
add page : .aspx and aspx.cs files
Masterpage app.component.html acts as Master page
Masterpage cs file app.component.ts code behind file for master page
Reusable forms Templates usercontrols
start up main.ts >> app.module.ts startup.cs, program.cs
Add model ng g class Modelname add cs file
Add Service ng g service servicename add cs file
Common resources static files storage Assets wwwroot or styles or scripts folder.
Navigation / Menu Routing/ nav.
ng generate module app-routing --flat --module=app
Menu / html
Navigation Container routes: Routes and use container <router-outlet></router-outlet> in master / landing page not available
Page Navigation: TS file: this.router.navigate([this.returnUrl])
html : <a routerLink="/Nav1"> Navigation1 </a>
cs: Response.Redirect, Server.Trasfer
html: <a href='' />
Page Lifecycle events ngOnchanges, ngOnInit, ngDoCheck, ngAfterContentInit, ngAfterContentCheck, ngAfterViewInit, ngAfterViewcheck, ngDestroy Init, load, validate, eventhandling, prerender, render
Coding:    
Current Instance this (mandatory to use) this (optional)
debugging debugger; and this.showSpinner=false; commonly used. Same as jquery. break point
Declaration custId :number int CustId
Commonly used Data types number, string, Date, boolean int, double, float, string, DateTime, boolean.
constructor constructor(protected http: HttpClient) same as class name
function declaration method name(params):returntype
example: authenticateUser(userLogin:UserLogin):Observable<UserLogin> {}
onSelect(selCust:Customer) {
}
return type Methodname(params)
Example:
UserLogin Authenticate(string Username, string Password)
{}
condition if(condition)
in html : *ngIf
if(condition)
loop in ts file: for(let a in array){}
html file directive: *ngFor="let curCust of custList"
foreach(var a in list){}
Binding from code to html {{curCust.custId}} Server control: controlID.Text
Two way binding [(ngModel)]="variable" not available
accessing DOM html in code file get f() { return this.FormGroupname.controls; }
this.variable=this.f.controlname.value;
runat=server, can access in code behind.
Submit form form Submit (ngSubmit)="onSubmit()" form postback
Event binding <button (click)="onClickMe()">Click me!</button>
<input (keyup)="onKey($event)">
object.event + = new delegate(method)

HTML DOM functions are valid like document.getElementById importing FormsModule.

Open app.component.html and delete content and add Navigation content.

Image 5

App.module.cs

Import Required Modules. Here, FormsModule (forms controls and F, HttpModule(http Requests), HttpClient (API calls and service implementation).

Image 6

Classes

userLogin, customer are two classes with required properties.

Services

These are responsible for making API calls using http protocol. This imports HttpClient, HttpHeaders, HttpParams, RequestContentType, HttpResponse modules, which provides required classes. This coding is the same as XMLHttpRequest.,Rxjs.

Image 7

Image 8

Components

Login

Formgroup, controls validation and error display are same as HTML.

OnForm Submit, get username, password from form controls and call authenticateUser API, if credentials are valid returns currentUser with token, which has stored in localStorage (HTML 5 features can be accessed across components. Saves as key value pair.).

CustomerList

This has HTML table to display Customer List. *ngFor Structure directive will loop through customerlist and to create <tr>. (click) to select tr / currCustomer.

ngOnInt event fires while initializing page, in this event makes a call to getAllcustomer API to get Customers.

CustomerDetail Component

This is simple FormsControl page to create Customer.

Common Errors

Access to XMLHttpRequest at 'http://localhost:5327/api/Customer//GetAllCustomer' from origin 'http://localhost:4200' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

Cause: CORS is not enabled.
Solution: CORS has to be enabled in startup.cs file. Can be done in other ways too.

401 Error: Unauthorized:

Cause: Authorize Bearer Token is the issue. Syntax not correct, Token not valid or Token Validation in API is not correct.
Solution: debug and find api address, and Token syntax. for .NET Core Version 2.0, add app.UseAuthentication() in startup.cs/Configure function.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)