HI WELCOME TO SIRIS

Angular 8 User Registration with Web API

Leave a Comment
In this tutorial, we will implement Angular 8 User Registration Using Web API and ASP.Net Identity.

Contents discussed :

Design angular 8 user registration form with required validations
How to use Asp.Net Identity in Web API
Customize Asp.Net Identity Table Structure
Here is the complete article list.

User Registration.
Login & Logout using Token.
Role Based Authorization.
Following tools and modules are used for this project :
– Angular CLI
– Angular 8
– ngx-Toastr (npm package)
– Materialize CSS (front end framework)
– VS Code & Visual Studio Editor

we assume that you have installed required packages and softwares for angular 8 development.

GitHub link for demo project : https://goo.gl/6bZM71

Related Angular 8 Articles : –

Angular 8 CRUD Operations With Web API.
Angular 8 CRUD Operations With Firebase.
Create Angular 8 Project
First of all we will create the Angular 5 Project and then Web API Project. I use Visual Studio Code Editor for Angular 8 App Development. To create an angular application, you can use following Angular CLI command

ng new Angular8

It will create an angular application with name Angular8  and install some default npm packages. In-order to run this application, following command can be used

ng serve --open

it will compile and open our application from default port number 4200 ( http://localhost:4200 ).

Let’s Start Application Design
In-order to design this application, we use Materialize CSS, it is one of the trending front end framework. jQuery library is need to work the framework script file. So let’s add the required style sheet and script references inside index.html.

/src/index.html

<head>
...
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/css/materialize.min.css">
</head>
<body style="background-color:#7599b3">
...
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/js/materialize.min.js"></script>
</body>

<head>
...
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/css/materialize.min.css">
</head>
<body style="background-color:#7599b3">
...
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/js/materialize.min.js"></script>
</body>

Now let’s update the global style sheet – styles.css. Inside the file we have added all css rules for entire application.

/src/styles.cssCSS
div.sm-jumbotron{
    margin: 0px;
    padding: 2rem;
    background-color: #38547b;
    color: #fff;
}

button.btn-submit{
    background-color: #38547b;
    color: #fff;
    width: 100%;
}
button.btn-submit:focus,button.btn-submit:hover{
    background-color: #38547b;
}

div.sm-jumbotron{
    margin: 0px;
    padding: 2rem;
    background-color: #38547b;
    color: #fff;
}

button.btn-submit{
    background-color: #38547b;
    color: #fff;
    width: 100%;
}
button.btn-submit:focus,button.btn-submit:hover{
    background-color: #38547b;
}
Create Angular 8 Component, Service Class and Model Class
We need one sign-up component. so let’s execute the following Angular CLI command

ng g c sign-up
To save service and model class, we will create a new shared folder. then to create these classes execute following commands.

//from shared folder
//for service class
ng g s user
//for model class
ng g class user --type=model


//from shared folder
//for service class
ng g s user
//for model class
ng g class user --type=model
Open newly created model class – user.model.ts file. let’s add required properties for user registration.

/src/app/shared/user.model.ts

export class User {
    UserName: string;
    Password: string;
    Email: string;
    FirstName: string;
    LastName: string;
}

export class User {
    UserName: string;
    Password: string;
    Email: string;
    FirstName: string;
    LastName: string;
}
Now update default component html ( app.component.html ) as follows.

/src/app/app.component.html

<div class="container">
  <app-sign-up></app-sign-up>
</div>

app-sign-up tag will be replaced by the sign-up component html.

Design User Registration Form
First of all let’s add a property of the type User model class inside sign-up component.

/src/app/sign-up/sign-up.component.ts
...
import { User } from '../shared/user.model';
@Component({
  selector: 'app-sign-up',
  templateUrl: './sign-up.component.html',
  styleUrls: ['./sign-up.component.css']
})
export class SignUpComponent implements OnInit {
user: User;
...
}

...
import { User } from '../shared/user.model';
@Component({
  selector: 'app-sign-up',
  templateUrl: './sign-up.component.html',
  styleUrls: ['./sign-up.component.css']
})
export class SignUpComponent implements OnInit {
user: User;
...
}

user property can be used to design the user registration form. For that Template Driven Approach can be used. So we need to import FormsModule in app.module.ts file.

/src/app/app.module.ts

...
import { FormsModule} from '@angular/forms';
@NgModule({
   ...
   imports: [
   ...
   FormsModule
   ],
...



Now update sign-up.component.html file with following html code.

/src/app/sign-up/sign-up.component.html
<div class="row">
  <div class="col s8 offset-s2">
    <div class="card">
      <div class="sm-jumbotron center-align">
        <h2>User Registration</h2>
      </div>
      <form class="col s12 white" #userRegistrationForm="ngForm" (ngSubmit)="OnSubmit(userRegistrationForm)">
        <div class="row">
          <div class="input-field col s6">
            <input class="validate" type="text" name="UserName" #UserName="ngModel" [(ngModel)]="user.UserName" required>
            <label data-error="Required field!">UserName</label>
          </div>
          <div class="input-field col s6">
            <input class="validate" type="password" name="Password" #Password="ngModel" [(ngModel)]="user.Password" required  minlength="3">
            <label [attr.data-error]="Password.errors!=null?(Password.errors.required?'Required field!':'Minimum 3 characters needed'):''">Password</label>
          </div>
        </div>
        <div class="row">
          <div class="input-field col s12">
            <input class="validate" type="text" name="Email" #Email="ngModel" [(ngModel)]="user.Email" [pattern]="emailPattern">
            <label data-error="Invalid email!">Email</label>
          </div>
        </div>
        <div class="row">
          <div class="input-field col s6">
            <input type="text" name="FirstName" #FirstName="ngModel" [(ngModel)]="user.FirstName">
            <label>First Name</label>
          </div>
          <div class="input-field col s6">
            <input type="text" name="LastName" #LastName="ngModel" [(ngModel)]="user.LastName">
            <label>Last Name</label>
          </div>
        </div>
        <div class="row">
            <div class="input-field col s12">
              <button [disabled]="!userRegistrationForm.valid" class="btn-large btn-submit" type="submit">Submit</button>
            </div>
          </div>
      </form>
    </div>
  </div>
</div>


Registration form will look like this.

Screen shot of Angular 8 User Registration Form

Form Validation

As per the component html file, both UserName and Password are mandatory fields – so we have added required attribute to those controls. other than this required validation, we have added ‘minlength=3’ (minimum 3 charactors should be there) to Password text box and for preventing invalid email format ‘pattern=emailPattern’  attribute is added to email text box.

Here emailPattern property is added to sign-up component typescript and it is initialized with regular expression for evaluating email address as follows.

emailPattern = "^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$";

In-order to validate form controls, we have added css class validate to the controls and error message is added in respective label data-error attribute. Then materialize css will take care of the client side validation.

On form submission, OnSubmit function will be called. So we have to define this function in component typescript file. Before that we have to deal with User Service Class.

User Service Class
Inside registration form submit event, we have to insert a new user using a Web API project. we have not yet created the Web API Project, in that project we will have a web api method with URI ‘/api/User/Register’  to add new user inside SQL Server. So we can define a function to consume the Web API method inside the service class.

/src/app/shared/user.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import {  Response } from "@angular/http";
import {Observable} from 'rxjs';
import 'rxjs/add/operator/map';
import { User } from './user.model';

@Injectable()
export class UserService {
  readonly rootUrl = 'http://localhost:35257';
  constructor(private http: HttpClient) { }

  registerUser(user : User){
    const body: User = {
      UserName: user.UserName,
      Password: user.Password,
      Email: user.Email,
      FirstName: user.FirstName,
      LastName: user.LastName
    }
    return this.http.post(this.rootUrl + '/api/User/Register', body);
  }

}


rootUrl is initialised with Web API base url, function registerUser() will post user model data to the Web API method using HttpClient object. In-order to use HttpClient, HttpClientModule class must be imported in app.module.ts file.

/src/app/app.module.ts
...
import { HttpClientModule } from '@angular/common/http';
@NgModule({
   ...
   imports: [
   ...
   HttpClientModule
   ],
...

ngx-toastr package installation

From sign-up component, we need to show notification messages after user registration, for that we can use npm package – ngx-toastr. In-order to install the package, you can use following npm command.

npm install ngx-toastr --save

then add ToastrModule inside appmodule.ts file. along with have to add User service class in providers array – because we need to inject the class in sign-up component.

/src/app/app.module.ts
...
import { ToastrModule } from 'ngx-toastr';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { UserService } from './shared/user.service';
@NgModule({
   ...
   imports: [
   ...
   ToastrModule.forRoot(),
   BrowserAnimationsModule
   ],
   providers: [UserService]
...

BrowserAnimationsModule is needed to work some UI-animation from the package. Now you can add following code in sign-up.component.ts file.

/src/app/sign-up/sign-up.component.ts

import { Component, OnInit } from '@angular/core';
import { User } from '../shared/user.model';
import { NgForm } from '@angular/forms';
import { UserService } from '../shared/user.service';
import { ToastrService } from 'ngx-toastr'

@Component({
  selector: 'app-sign-up',
  templateUrl: './sign-up.component.html',
  styleUrls: ['./sign-up.component.css']
})
export class SignUpComponent implements OnInit {
  user: User;
  emailPattern = "^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$";

  constructor(private userService: UserService, private toastr: ToastrService) { }

  ngOnInit() {
    this.resetForm();
  }

  resetForm(form?: NgForm) {
    if (form != null)
      form.reset();
    this.user = {
      UserName: '',
      Password: '',
      Email: '',
      FirstName: '',
      LastName: ''
    }
  }

  OnSubmit(form: NgForm) {
    this.userService.registerUser(form.value)
      .subscribe((data: any) => {
        if (data.Succeeded == true) {
          this.resetForm(form);
          this.toastr.success('User registration successful');
        }
        else
          this.toastr.error(data.Errors[0]);
      });
  }

}


inside the component, we have injected UserService class and ToastrService class (from ngx-Toastr). resetForm() function will reset the form controls to their initial state.

With OnSubmit() function, we called UserService function registerUser() for user registration, which in turn submit the form data to Web API method to Insert a new user.

Create Web API Project
To create the Web API Project,Open your Visual Studio. In-order to create a new project, go to FILE > New > Project (Ctrl + Shift + N).

Image Showing Creation Of Asp.Net MVC Project

Then select Web API template. then Click On Change Authentication and Make sure that we have selected No Authentication Option.

Select MVC Template

So here we have created a brand new Web API Project.

Add Asp.Net Identity to Asp.Net Application
Asp.Net Identity is a membership system for Asp.Net Applications. It provides lot of feature like User Management, Role Management, User Authentication and Authorization, Social Logins with Facebook, gmail, twitter etc. In this article, we will use Asp.net Identity  to store user details inside Identity tables.

First of install required package for Asp.Net Identity. Right click on the project, then Manage NuGet Packages… , then search(Online) and Install Microsoft ASP.NET Identity EntityFramework.

Asp.Net Identity uses Code First Approach, So table structure inside the membership system is already defined, if you want to customize the structure, we have to do some additional works. First of all add IdentityModels file inside Models folder as follows.

/Models/IdentityModels.csC#

public class ApplicationUser : IdentityUser
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

public class ApplicationDbContext : IdentityDbContext<ApplicationUser> {

    public ApplicationDbContext()
        : base("DefaultConnection", throwIfV1Schema: false)
    {
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        //AspNetUsers -> User
        modelBuilder.Entity<ApplicationUser>()
            .ToTable("User");
        //AspNetRoles -> Role
        modelBuilder.Entity<IdentityRole>()
            .ToTable("Role");
        //AspNetUserRoles -> UserRole
        modelBuilder.Entity<IdentityUserRole>()
            .ToTable("UserRole");
        //AspNetUserClaims -> UserClaim
        modelBuilder.Entity<IdentityUserClaim>()
            .ToTable("UserClaim");
        //AspNetUserLogins -> UserLogin
        modelBuilder.Entity<IdentityUserLogin>()
            .ToTable("UserLogin");
    }
}


ApplicationUser  class is inherited from IdentityUser. In IdentityUser class, Asp.Net Identity defined the default properties for Identity table (like Username,Email, PasswordHash etc). Inside ApplicationUser  class we have added additional two properties to User details table – FirstName and LastName.
Configure DB Connection
Inside IdentityModels.cs file, we have ApplicationDbContext class which inherits IdentityDbContext class from Asp.Net Identity. With the class constructor, we have configured the DB connection. as part of that we have to add DB connection string  in Web.config file with DefaultConnection name as follows.

web.config
...
<configuration>
...

<connectionStrings>
  <add name="DefaultConnection" connectionString="Data Source=(local)\sqle2012;Initial Catalog=UserDB;Integrated Security=True" providerName="System.Data.SqlClient" />
</connectionStrings>

</configuration>


This connection string will be used for Asp.Net Identity Code First Approach With UserDB Database. You can use all of your application data along Identity table inside this same database or you can have a separate DB for Application Data (Data except User Management and Role Management), in that case you may have to add one more connection string.

Back to ApplicationDbContext class, there we have overridden OnModelCreating from Asp.Net Identity to change the default identity table names.

Now in-order to see these changes in action. Go to Tools > Library Package Manager > Package Manager Console.

In code first application, Database table structure are defined in C# code, in-order to see them as database objects first of all we have to enable migration for that execute following Command.

enable-migrations

then add a migration –  it’s like restore point in windows

add migration InitialMigration

to see these changes in database, execute following update command

update-database

Now if you check the database as per web config connection string you can see tables from Asp.Net Identity with our customization.

Add Web API Controller for User Registration

Now let’s add Web API controller for user registration. Right click on Controllers folder, Add > Controller. I’ll name this controller as AccountController. Inside the controller we need a Web API method Register to Post registration data from Angular 8 application. Finally the controller will be as follows.

/Controllers/AccountController.csC#

public class AccountController : ApiController
{
    [Route("api/User/Register")]
    [HttpPost]
    public IdentityResult Register(AccountModel model)
    {
        var userStore = new UserStore<ApplicationUser>(new ApplicationDbContext());
        var manager = new UserManager<ApplicationUser>(userStore);
        var user = new ApplicationUser() { UserName = model.UserName, Email = model.Email };
        user.FirstName = model.FirstName;
        user.LastName = model.LastName;
        manager.PasswordValidator = new PasswordValidator
        {
            RequiredLength = 3
        };
        IdentityResult result = manager.Create(user, model.Password);
        return result;
    }
}


As per Asp.Net Identity, Password should be at least 6 characters long. Inside the method we reduced minimum number of characters to 3. As a parameter for this we an object of AccountModel class. So let’s add this class inside Models Folder.

/Models/AccountModel.csC#
public class AccountModel
{
    public string UserName { get; set; }
    public string Email { get; set; }
    public string Password { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

So here we have done with this Web API Project.

But there is a Problem – CORS

CORS (Cross-Origin Resource Sharing) : it is a mechanism to let a user agent (browser) gain permission to access selected resources from a server on a different origin (domain) than the site currently in use. cross-origin HTTP request occurs when it requests a resource from a different domain, protocol, or port than the one from which the current document originated.

In this application, our web API project will block request from angular 8 application, since they are cross-origin HTTP request(from different port number – 4200). In-order to allow cross-origin HTTP request, we have to configure Web API project for this localhost:4200 request. so let’s look how we can do that.

First of we have to install NuGet Package : WebApi.Cors. Back to Visual Studio, Select your Web API project from solution explorer, then go to Tools > Library Package Manager > Package Manager Console. use following NuGet command to install WebApi.Cors.

Install-Package Microsoft.AspNet.WebApi.Cors

Now let’s look how we can use this package. In-order allow cross-origin request in Web API project, Go to App_Start >WebApiConfig.cs file. add following lines of code
/App_Start/WebApiConfig.csC#
...
using System.Web.Http.Cors;

public static class WebApiConfig
{
   public static void Register(HttpConfiguration config)
   {
       config.EnableCors(new EnableCorsAttribute("http://localhost:4200", headers: "*", methods: "*"));
       ...


now web API project is ready for cross-origin request from our angular 8 application.
Now try run this application without debug mode, some of you may get this problem.

Could not load file or assembly System.Web.Http

It is due to different version of latest WebApi.Cors and System.Web.Http (5.0.0), so lets install same version of WebApi.Core (Not Cors it is Core). it will resolve this assembly problem. for that you can run following NuGet Command from Package Manager Console.

Update-Package Microsoft.AspNet.WebApi -reinstall
Install-Package Microsoft.AspNet.WebApi.Core

So here we have successfully implemented Angular 8 User Registration with Web API. In the next part, we’ll discuss Login and Logout in Angular 8 Using Based Authentication and Web API.

0 comments:

Post a Comment

Note: only a member of this blog may post a comment.