Remove image from Browser Cache when Image changes using Asp.Net C# and Vb.Net

<p><em style="color: rgb(108, 131, 154);">Browsers, cache images and other static assets on a website, to reduce upload time and bandwidth. This process helps websites load faster, by extracting contents from the cache (a temporary storage in your computer). However, sometimes you need clear the browser cache, if the websites contents change frequently, such as images. I am sharing a simple trick here, which shows how to load clear browser cache when image changes using Asp.Net C# and Vb.Net.</em></p><p>I was recently updating my <em>Easy Image Resizer tool</em>, and I noticed that every time I select an <em>image for resizing or cropping</em>, the browser shows the previously selected image, instead of the new image. This is the browser’s default behavior. I had to overcome this issue and I figured out that the solution to this problem is simple. It’s a trick rather.</p><p>Browsers don’t <em style="background-color: rgb(238, 238, 238); color: rgb(0, 0, 0);">scan</em> every image (or any content) to check if it’s the same as before. Browser cache works by identifying objects, such as images, by its <em style="background-color: rgb(238, 238, 238); color: rgb(0, 0, 0);">name</em>.</p><p>Since I am using Asp.Net, I can simply change the name of the image at the server side itself, by concatenating the image name with <em style="background-color: rgb(238, 238, 238); color: rgb(0, 0, 0);">date and time</em> (since its always unique), and send the image (with a new name every time) to the browser.</p><p>Here’s how you should do this.</p><p><strong><em>The Markup</em></strong></p><pre class="ql-syntax" spellcheck="false"><img id=<span class="hljs-string">"myImage"</span> alt=<span class="hljs-string">"image"</span> src=<span class="hljs-string">""</span> style=<span class="hljs-string">"border:none;max-width:100%;"</span> runat=<span class="hljs-string">"server"</span> /> </pre><p>
</p><p><strong><em>Code in C#</em></strong></p><pre class="ql-syntax" spellcheck="false">protected <span class="hljs-keyword">void</span> Page_Load(object sender, EventArgs e) { myImage.Src = <span class="hljs-string">""</span>; myImage.Src = <span class="hljs-string">"~/car.png"</span> + <span class="hljs-string">"?"</span> + DateTime.Now.Ticks.ToString(); <span class="hljs-comment">// Add date time to prevent caching.</span> } </pre><p>Here's how it shows the image name in the browser console window.</p><p class="ql-align-center">Remove image from Browser Cache when image changes using Asp.Net</p><p>The code concatenates a new date and time with the image name for every page load, thereby receiving a new source name for the same image.</p><p><strong style="color: rgb(0, 0, 0);"><em>Note</em></strong>: If you have a habbit of storing your images into a database, this technique useful. Simply, <em style="background-color: rgb(238, 238, 238); color: rgb(0, 0, 0);">concatenate</em> the date and time with image name and save it. Date and time are always different.</p><p><strong><em>Vb.Net</em></strong></p><pre class="ql-syntax" spellcheck="false">myImage.Src = "" myImage.Src = "~/car.png" & "?" & DateTime.Now.Ticks.ToString ' Add date time to prevent caching. </pre><p>This process is simple, and you can easily get the name of the image by simply replacing the string after the <em style="background-color: rgb(238, 238, 238); color: rgb(0, 0, 0);">?</em> character.</p><p>Well, that’s it. Thanks for reading.</p>

How to Login and Registration ASP.NET Web API with Angular 8

How to Login and Registration ASP.NET Web API with Angular 8

In this article, we will learn the step by step process of creating login and registration pages in a Web API with Angular 8 using the following technologies:

  • ASP.NET Web API.
  • Angular 8.
  • SQL Server.
  • Bootstrap.

You may also like: Angular 8 HttpClient & Http Tutorial – Build and Consume RESTful API.

Prerequisites

  • Basic knowledge of Angular and Web API.
  • Visual Studio Code and Visual Studio IDE should be installed.
  • SQL Server Management Studio.
  • Nodejs should be installed.

Step 1

Open SQL Server Management Studio, create a database named Employee, and in this database, create a table. Give that table a name like Employeemaster.

CREATE TABLE [dbo].[Employeemaster](  
    [UserId] [int] IDENTITY(1,1) NOT NULL,  
    [UserName] [varchar](50) NOT NULL,  
    [LoginName] [varchar](50) NULL,  
    [Password] [varchar](50) NOT NULL,  
    [Email] [varchar](50) NULL,  
    [ContactNo] [varchar](15) NULL,  
    [Address] [varchar](50) NULL,  
    [IsApporved] [int] NULL,  
    [Status] [int] NULL,  
    [TotalCnt] [int] NULL,  
PRIMARY KEY CLUSTERED   
(  
    [UserId] ASC  
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]  
) ON [PRIMARY]  

GO  

Now, create a stored procedure with the name, Usp_Login for adding the login functionality.

create proc  [dbo].[Usp_Login]  
@UserName varchar(50)='',  
@Password varchar(50)=''  
as begin  
    declare @UserId int =0,@TotalCnt int =0  
    select @UserId=UserId,@TotalCnt=TotalCnt from  Employeemaster um   
    where [email protected] and [email protected] and Status<>3 and IsApporved=1  
    if(@TotalCnt>=5)  
    begin  
       select 0 UserId,'' UserName,'' LoginName,'' Password,'' Email,'' ContactNo,   
    ''Address,0 IsApporved,-1 Status  
    end  
    if(@UserId>0)  
    begin  
        select UserId, UserName, LoginName, Password, Email, ContactNo,   
        Address, IsApporved, Status from  Employeemaster um   
        where [email protected]   
        --update  Employeemaster  set  Status=2 where [email protected]   

    end  
    else  
    begin  
       Update Employeemaster set @TotalCnt=TotalCnt+1    
       where [email protected] and Status=1 and IsApporved=1  
       select 0 UserId,'' UserName,'' LoginName,'' Password,'' Email,'' ContactNo,   
    ''Address,0 IsApporved,0 Status  
    end  
    end  

Step 2

Open Visual Studio and create a new project.

Create Registration And Login Page Using Angular 7 And Web API

<figcaption style="text-align:center">_Create Registration And Login Page Using Angular 7 And Web API_</figcaption>

Change the name as LoginAPI and select Web API as its template.

Create Registration And Login Page Using Angular 7 And Web API

Step 3

Right-click the Models folder from Solution Explorer and go to Add >> New Item >> data. Create Registration And Login Page Using Angular 7 And Web API

Click on the ADO.NET Entity Data Model option and click Add. Create Registration And Login Page Using Angular 7 And Web API

Select EF designer from the database and click the Next button.

Create Registration And Login Page Using Angular 7 And Web API

Add the connection properties, select database name on the next page, and click OK. Create Registration And Login Page Using Angular 7 And Web API

Check the Tables and Stored procedure checkboxes. The internal options will be selected by default. Now, click the Finish button.

Create Registration And Login Page Using Angular 7 And Web API

Our data model is created now.

Step 4

Right-click on the Models<span id="_tmp_pre_4"> </span>folder and add two classes — Login<span id="_tmp_pre_5"> </span>and Response respectively. Now, paste the following codes in these classes.

using LoginAPI.Models;   

Step 5

Right-click on the Controllers folder and add a new controller. Name it as Logincontroller.

Add the following namespace in the Login controller.

[Route("Api/Login/createcontact")]  
       [HttpPost]  
       public object createcontact(Registration Lvm)  
       {  
           try  
           {  
               DemologinEntities db = new DemologinEntities();  
               Employeemaster Em = new Employeemaster();  
               if (Em.UserId == 0)  
               {  
                   Em.UserName = Lvm.UserName;  
                   Em.LoginName = Lvm.LoginName;  
                   Em.Password = Lvm.Password;  
                   Em.Email = Lvm.Email;  
                   Em.ContactNo = Lvm.ContactNo;  
                   Em.Address = Lvm.Address;  
                   Em.IsApporved = Lvm.IsApporved;  
                   Em.Status = Lvm.Status;  
                   db.Employeemasters.Add(Em);  
                   db.SaveChanges();  
                   return new Response  
                   { Status = "Success", Message = "SuccessFully Saved." };  
               }  
           }  
           catch (Exception)  
           {  

               throw;  
           }  
           return new Response  
           { Status = "Error", Message = "Invalid Data." };  
       }   

Now, add a method to insert data into the database for user registration.

[Route("Api/Login/UserLogin")]  
       [HttpPost]  
       public Response Login(Login Lg)  
       {  
           DemologinEntities DB = new DemologinEntities();  
           var Obj = DB.Usp_Login(Lg.UserName, Lg.Password).ToList<Usp_Login_Result>().FirstOrDefault();  
           if (Obj.Status == 0)  
               return new Response { Status = "Invalid", Message = "Invalid User." };  
           if (Obj.Status == -1)  
               return new Response { Status = "Inactive", Message = "User Inactive." };  
           else  
               return new Response { Status = "Success", Message = Lg.UserName };  
       }  

Step 6

Add a new method for logging into the Login controller with the following lines of code.

using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Net;  
using System.Net.Http;  
using System.Web.Http;  
using LoginAPI.Models;  

namespace LoginAPI.Controllers  
{  
    public class LoginController : ApiController  
    {  

        //For user login   
        [Route("Api/Login/UserLogin")]  
        [HttpPost]  
        public Response Login(Login Lg)  
        {  
            DemologinEntities DB = new DemologinEntities();  
            var Obj = DB.Usp_Login(Lg.UserName, Lg.Password).ToList<Usp_Login_Result>().FirstOrDefault();  
            if (Obj.Status == 0)  
                return new Response { Status = "Invalid", Message = "Invalid User." };  
            if (Obj.Status == -1)  
                return new Response { Status = "Inactive", Message = "User Inactive." };  
            else  
                return new Response { Status = "Success", Message = Lg.UserName };  
        }  

        //For new user Registration  
        [Route("Api/Login/createcontact")]  
        [HttpPost]  
        public object createcontact(Registration Lvm)  
        {  
            try  
            {  
                DemologinEntities db = new DemologinEntities();  
                Employeemaster Em = new Employeemaster();  
                if (Em.UserId == 0)  
                {  
                    Em.UserName = Lvm.UserName;  
                    Em.LoginName = Lvm.LoginName;  
                    Em.Password = Lvm.Password;  
                    Em.Email = Lvm.Email;  
                    Em.ContactNo = Lvm.ContactNo;  
                    Em.Address = Lvm.Address;  
                    Em.IsApporved = Lvm.IsApporved;  
                    Em.Status = Lvm.Status;  
                    db.Employeemasters.Add(Em);  
                    db.SaveChanges();  
                    return new Response  
                    { Status = "Success", Message = "SuccessFully Saved." };  
                }  
            }  
            catch (Exception)  
            {  

                throw;  
            }  
            return new Response  
            { Status = "Error", Message = "Invalid Data." };  
        }  
    }  

}  

Complete Login controller

EnableCorsAttribute cors = new EnableCorsAttribute("*", "*", "*");  
config.EnableCors(cors);  

Step 7

Now, let's enable Cors. Go to Tools, open NuGet Package Manager, search for Cors, and install the "Microsoft.Asp.Net.WebApi.Cors" package. Create Registration And Login Page Using Angular 7 And Web API Open Webapiconfig.cs and add the following lines.

ng new login

Step 8

Create an Angular 8 project with a name "login" by using the following command.

npm install bootstrap --save

Step 9

Open Visual Studio Code, open the newly created project and add bootstrap to this project.

export class Register {  
    UserName:string;  
    LoginName:string;  
    Password:string;  
    Email:string;  
    ContactNo:string;  
    Address:string  
} 

Step 10

Now, create three components for the login page, registration page, and dashboard respectively. To create the components, open terminal and use the following commands.

  • ng g c login
  • ng g c register
  • ng g c dashboard

Create Registration And Login Page Using Angular 7 And Web API

Step 11

Create a class named "register". ng g class register Add the required properties in the class.

ng g s login 

Step 12

Create a service to call the Web API.

import { Injectable } from '@angular/core';  
import {HttpClient} from '@angular/common/http';  
import {HttpHeaders} from '@angular/common/http';  
import { from, Observable } from 'rxjs';  
import { Register } from "../app/register";  
@Injectable({  
  providedIn: 'root'  
})  
export class LoginService {  
  Url :string;  
  token : string;  
  header : any;  
  constructor(private http : HttpClient) {   

    this.Url = 'http://localhost:14812/api/Login/';  

    const headerSettings: {[name: string]: string | string[]; } = {};  
    this.header = new HttpHeaders(headerSettings);  
  }  
  Login(model : any){  
    debugger;  
     var a =this.Url+'UserLogin';  
   return this.http.post<any>(this.Url+'UserLogin',model,{ headers: this.header});  
  }  
   CreateUser(register:Register)  
   {  
    const httpOptions = { headers: new HttpHeaders({ 'Content-Type': 'application/json' }) };  
    return this.http.post<Register[]>(this.Url + '/createcontact/', register, httpOptions)  
   }  
}  

Open the login service and import required packages and classes. Add the following lines of code in the login.service.ts file.

<div class="container" style="padding-top:40px;">  
    <div class="row">  
      <div class="col-md-6 mx-auto">  
        <div class="card mx-4">  
          <div class="card-body p-4">  
            <form [formGroup]="employeeForm" (ngSubmit)="onFormSubmit(employeeForm.value)">  
              <h1 style="text-align:center">Register</h1>  

              <div class="input-group mb-3">  

                <input type="text" class="form-control" placeholder="Username"  formControlName="UserName">  
              </div>  
              <div class="input-group mb-3">  
                <input type="text" class="form-control" placeholder="Loginname"  formControlName="LoginName">  
              </div>  
              <div class="input-group mb-3">  
                <input type="password" class="form-control" placeholder="Password"  formControlName="Password">  
              </div>  
              <div class="input-group mb-4">  
                <input type="text" class="form-control" placeholder="Email"  formControlName="Email">  
              </div>  
              <div class="input-group mb-4">  
                <input type="text" class="form-control" placeholder="Contact No"  formControlName="ContactNo">  
              </div>  
              <div class="input-group mb-4">  
                <input type="text" class="form-control" placeholder="Address"  formControlName="Address">  
              </div>  
              <button type="submit" class="btn btn-block btn-success">Add User</button>  
            </form>  
          </div>  
        </div>  
      </div>  
    </div>  
  </div>  

Step 13

Now, open register.component.html and add the following HTML code to design the registration form.

import { Component, OnInit } from '@angular/core';    
import { LoginService } from '../login.service';    
import {Register} from '../register';    
import {Observable} from 'rxjs';    
import { NgForm, FormBuilder, FormGroup, Validators, FormControl } from '@angular/forms';    

@Component({    
  selector: 'app-register',    
  templateUrl: './register.component.html',    
  styleUrls: ['./register.component.css']    
})    
export class RegisterComponent implements OnInit {    
  data = false;    
  UserForm: any;    
  massage:string;    
  constructor(private formbulider: FormBuilder,private loginService:LoginService) { }    

  ngOnInit() {    
    thisthis.UserForm = this.formbulider.group({    
      UserName: ['', [Validators.required]],    
      LoginName: ['', [Validators.required]],    
      Password: ['', [Validators.required]],    
      Email: ['', [Validators.required]],    
      ContactNo: ['', [Validators.required]],    
      Address: ['', [Validators.required]],    
    });    
  }    
   onFormSubmit()    
  {    
    const user = this.UserForm.value;    
    this.Createemployee(user);    
  }    
  Createemployee(register:Register)    
  {    
  this.loginService.CreateUser(register).subscribe(    
    ()=>    
    {    
      this.data = true;    
      this.massage = 'Data saved Successfully';    
      this.UserForm.reset();    
    });    
  }    
}    

Step 14

Open register.componet.ts file and add following lines.

<div class="container" style="padding-top:60px;">  
  <div class="row">  
    <div class="col-md-6 mx-auto">  
      <div class="card-group">  
        <div class="card p-4">  
          <div class="card-body">  
            <form name="form" (ngSubmit)="login()" #f="ngForm">   
              <h1 style="text-align:center">Login</h1>  

              <div class="input-group mb-3">  
                <div class="input-group-prepend">  
                  <span class="input-group-text"><i class="icon-user"></i></span>  
                </div>  
                <input type="text" name="UserName" [(ngModel)]="model.UserName" class="form-control sty1" placeholder="Email" required>  
              </div>  
              <div class="input-group mb-4">  
                <div class="input-group-prepend">  
                  <span class="input-group-text"><i class="icon-lock"></i></span>  
                </div>  
                <input  type="password" name="Passward" [(ngModel)]="model.Password" class="form-control"  
               placeholder="Password">  
              </div>  
              <div>  
                  <p style="color:#E92626;font-size:20px;font-weight:normal" Class="success" align="left">  
                    {{errorMessage}}  
                  </p>  
                </div>  
              <div class="row">  
                <div class="col-6">  
                  <button type="submit" class="btn btn-primary px-4">Login</button>  
                </div>  
                <div class="col-6 text-right">  
                  <button type="button" class="btn btn-link px-0">Forgot password?</button>  
                </div>  
              </div>  

            </form>  
          </div>  
        </div>  
      </div>  
    </div>  
  </div>  
</div>  

Step 15

Open login.componet.html and add this HTML.

import { Component, OnInit } from '@angular/core';    
import { Router } from '@angular/router';    
import { LoginService } from '../login.service';    
 import { FormsModule } from '@angular/forms';    

@Component({    
  selector: 'app-login',    
  templateUrl: './login.component.html',    
  styleUrls: ['./login.component.css']    
})    
export class LoginComponent {    

  model : any={};    

  errorMessage:string;    
  constructor(private router:Router,private LoginService:LoginService) { }    

  ngOnInit() {    
    sessionStorage.removeItem('UserName');    
    sessionStorage.clear();    
  }    
  login(){    
    debugger;    
    this.LoginService.Login(this.model).subscribe(    
      data => {    
        debugger;    
        if(data.Status=="Success")    
        {       
          this.router.navigate(['/Dashboard']);    
          debugger;    
        }    
        else{    
          this.errorMessage = data.Message;    
        }    
      },    
      error => {    
        this.errorMessage = error.message;    
      });    
  };    
 }    

Open login.componet.ts and add following code.

<div>  
  <div class="row">  
    <div class="col-sm-12 btn btn-primary">  
        Welcome to DashBoard  
    </div>  
  </div>  
</div>  

Step 16

Now, open dashboard.component.html and add the following lines.

import { NgModule } from '@angular/core';    
import { Routes, RouterModule } from '@angular/router';    
import { DashboardComponent } from './dashboard/dashboard.component';    
import { LoginComponent } from './login/login.component';    
import { RegisterComponent } from './register/register.component';    

export const routes: Routes = [    
  {    
    path: '',    
    redirectTo: 'login',    
    pathMatch: 'full',    
  },    
  {    
    path: 'login',    
    component: LoginComponent,    
    data: {    
      title: 'Login Page'    
    }    
  },    
  {    
    path: 'Dasboard',    
    component: DashboardComponent,    
    data: {    
      title: 'Dashboard Page'    
    }    
  },    
  {    
    path: 'AddUser',    
    component: RegisterComponent,    
    data: {    
      title: 'Add User Page'    
    }    
  },    
];    

@NgModule({    
  imports: [RouterModule.forRoot(routes)],    
  exports: [RouterModule]    
})    
export class AppRoutingModule { } 

Step 17

Now, open app-routing.module.ts file and add the following lines to create routing

import { NgModule } from '@angular/core'; 
import { Routes, RouterModule } from '@angular/router'; 
import { DashboardComponent } from './dashboard/dashboard.component'; 
import { LoginComponent } from './login/login.component'; 
import { RegisterComponent } from './register/register.component'; 

export const routes: Routes = [ 
  { path: '', redirectTo: 'login', pathMatch: 'full', }, 
  { path: 'login', component: LoginComponent, data: { title: 'Login Page' } }, 
  { path: 'Dasboard', component: DashboardComponent, data: { title: 'Dashboard Page' } }, 
  { path: 'AddUser', component: RegisterComponent, data: { title: 'Add User Page' } }, 
]; 

@NgModule({ 
  imports: [RouterModule.forRoot(routes)], 
  exports: [RouterModule] 
}) 

export class AppRoutingModule { } 

Step 18

Now, let us run the project and redirect the URL to the "Add User" page.

Create Registration And Login Page Using Angular 7 And Web API

Enter the details and click on the "Add User" button.

Step 19

Now, run the project's default URL which takes us to the login page. Enter the username and password and click "Login".

Create Registration And Login Page Using Angular 7 And Web API

The following Page will be displayed.

Create Registration And Login Page Using Angular 7 And Web API

You may also like: Angular vs React vs Vue: Which one will be popular in 2020.

Summary

In this article, we discussed the process of Login and Registration page creation in an application with Angular 8 and Web API.

Thank you for reading ! If you enjoyed this article, please share it with others who may enjoy it as well.!

This 10 Features in Asp.Net Core you need to know

This 10 Features in Asp.Net Core you need to know

With the revolution of technology, today, we are living in an era where everything is under a few clicks. Whenever we try to google some words, then in milliseconds, we find thousands of websites created by web developers. In fact, they generate a lot of stuff ranging from web apps to desk apps to gaming apps or any other mobile apps.

The developers use various platforms to generate new things for us. A very popular platform is by Microsoft. A dynamic, cross-platform web development framework, apart from being free and open-source, is Asp.Net Core. It is an upgraded version of another framework by Microsoft named Asp.Net. It is freshly written from scratch. It comes with uniquely single programming model of two another famous web framework called ASP.NET MVC and ASP.NET Web API.

With regular updates and add on features, developers have to code now less compared to the earlier times. This enhances performance and better scalable web applications. Let’s look more closely about the Asp.Net Core features and other add-ons by Microsoft on Asp.Net Core.

10 Features help you to develop better ASP.NET Core apps

1. Cross-platform Functionality

One of the very crucial features of Asp.Net Core is its cross-platform functionality. This implies the fact that it can be run on several other platforms. So, if Asp.Net Core developer wants to build numerous applications and versions that too for different platforms like Windows or Linux or might be any other than Asp.Net Core is widely recommended. This functionality will allow the developers to easily edit their HTML, CSS, and JSON content frequently. And also help them in publishing the application made to the respective app store service. One of the essential features helped in Asp.Net Core development

2. Performance

No app or website is a success which does hang frequently and doesn’t work correctly. Hence, the application performance of the app is quite remarkable. Bothcoding and framework architecture defines its application performance. Asp.NetCore from Microsoft is one of the fastest development frameworks. ASP.Net Core application can manage around 1.15 million requests/second. So, surely Microsoft team make sure that this technology does not disappoint us in any domain.

3. Modular

There was a time when Asp.Net Core developers used to work with assemblies. But now with the increase of technology, they no more deal with meetings; instead, they promptly work with NuGet packages. During the era of the .Net Framework, all the framework updates used to work through Windows updates. But for .Net Core, it’s quite different since the responsibility of updates lies on the shoulder of the package manager. NuGet packages come with a lot of benefits like high security, enhanced performance, and also helps in reducing the servicing of web apps.

4. Trusted and secure

One of the prime focus of concern for Microsoft is providing security. If whenever they sense about any threat, an update is being followed immediately to enhance the trust and safety in the system.

5. Vast Ecosystem

Another feature which you may purchase from the .Net ecosystem is several libraries from your NuGet package manager, partner network and also Visual Studio Marketplace, there are arprox 50,000+ Asp.Net Core realted NuGet package available . With the help of the community, MVPs, and broad support network varieties of technical queries can be resolved.

6. Globalization and localization

When the content of your service is being provided on a multilingual website, it attracts a broader audience. Asp.Net Core extensively works quite well, helping to localize into numerous languages and cultures. The term globalization stands for the meaning that web applications are language and culture neutral, whereas localization is the process where a web application is specific to its location and culture.

Realted Article :

7. Self-hosting apps

One can host ASP.NET Core applications on Windows that too without the usage of IIS. Therefore, they are self-hosted and hosted for Linus distribution on Nginx. This implies that .NET Core application work well independently on all platforms available so that Asp.Net Core developer need not worry.

8. Open-source

As we know, .Net Core is not only open-source and cross-platform but also the updated version of .NET community. The open-source includes libraries, languages, compilers, ASP.NET Core web framework, windows desktop frameworks, and lastly entity framework core data access library. Open source an amazing Asp.Net Core feature. This feature had led to immense Asp.Net Core Development in the long run.

9. Minimum coding

With minimum lines of coding, an Asp.Net Core developer may reach the same position as if with numerous lines of coding just with the help if Asp.Net core. ASP.NET Core follows several standard APIs with the .NET Framework apart to APIs that are specific either to Unix, Linux, or OS X. Again; an attractive Asp.Net Core features apart from open-source, which is excellent for the overall development.

10. Unification of programming model

Before the existence of Asp.Net Core, developers had the option of using MVC and Web API frameworks broadly. With the presence of Asp.Net Core, the Developers get the advantages of both the web development framework helping in Asp.NetCore Development.

**Conclusion

Apart from the features as mentioned above of Asp.Net Core, we got a variety of other add-on feature. For instance, new Razor pages which work on familiar Razor syntax but are the replacement for WebForms. It rigorously supports for WebSockets, which is used to maintain long-running connections and communicate with the browser well. Another feature is extensible filters. These features were significant for Asp.Net Core development.

The biggest reason why Asp.Net core was adopted by most of the developers was the fact that it doesn’t require any new knowledge, which is a plus point.

This is for sure that Asp.Net Core is a significant upgrade which gathered a lot of eyes of the developers. Various add-ons are highlighting its aspects for all the Asp.Net Core developers. Therefore, Asp.Net core is powerful applications with outstanding performance and scalability.

Thank for reading! If you enjoyed this article, please share it with others who may enjoy it as well.!

Create a web API with ASP.NET Core MVC

Create a web API with ASP.NET Core MVC

In this tutorial, you learn how to:

  • Create a web API project.
  • Add a model class.
  • Create the database context.
  • Register the database context.
  • Add a controller.
  • Add CRUD methods.
  • Configure routing and URL paths.
  • Specify return values.
  • Call the web API with Postman.
  • Call the web API with jQuery.

At the end, you have a web API that can manage "to-do" items stored in a relational database.

Overview

This tutorial creates the following API:

Create a web API with ASP.NET Core MVC

The following diagram shows the design of the app.

Create a web API with ASP.NET Core MVC

Prerequisites

Visual Studio

Visual Studio 2019 with the ASP.NET and web development workload

.NET Core SDK 2.2 or later

Visual Studio Code

Visual Studio Code

.NET Core SDK 2.2 or later

C# for Visual Studio Code (latest version)

Visual Studio for Mac

Visual Studio for Mac version 7.7 or later

.NET Core SDK 2.2 or later

Create a Web API project

Visual Studio

  • From the File menu, select New > Project.
  • Select the ASP.NET Core Web Application template. Name the project TodoApi and click OK.
  • In the New ASP.NET Core Web Application - TodoApi dialog, choose the ASP.NET Core version. Select the API template and click OK. Do not select Enable Docker Support.

Create a web API with ASP.NET Core MVC

Visual Studio Code

Open the integrated terminal.

Change directories (cd) to the folder which will contain the project folder.

Run the following commands:

console

dotnet new webapi -o TodoApi
code -r TodoApi

These commands create a new web API project and open a new instance of Visual Studio Code in the new project folder.

When a dialog box asks if you want to add required assets to the project, select Yes.

Visual Studio for Mac

  • Select File > New Solution.
  • Create a web API with ASP.NET Core MVC
  • Select .NET Core App > ASP.NET Core Web API > Next.
  • Create a web API with ASP.NET Core MVC
  • In the Configure your new ASP.NET Core Web API dialog, accept the default Target Framework of *.NET Core 2.2.
  • Enter TodoApi for the Project Name and then select Create.
  • Create a web API with ASP.NET Core MVC

Test the API

The project template creates a values API. Call the Get method from a browser to test the app.

Visual Studio

Press Ctrl+F5 to run the app. Visual Studio launches a browser and navigates to [https://localhost:<port>/api/values](https://localhost:<port>/api/values), where <port> is a randomly chosen port number.

If you get a dialog box that asks if you should trust the IIS Express certificate, select Yes. In the Security Warning dialog that appears next, select Yes.

Visual Studio Code

Press Ctrl+F5 to run the app. In a browser, go to following URL: https://localhost:5001/api/values.

Visual Studio for Mac

Select Run > Start With Debugging to launch the app. Visual Studio for Mac launches a browser and navigates to [https://localhost:<port>](https://localhost:<port>), where <port> is a randomly chosen port number. An HTTP 404 (Not Found) error is returned. Append /api/values to the URL (change the URL to [https://localhost:<port>/api/values](https://localhost:<port>/api/values)).

The following JSON is returned:

JSON

<pre class="ql-syntax" spellcheck="false">["value1","value2"] </pre>

Add a model class

A model is a set of classes that represent the data that the app manages. The model for this app is a single TodoItem class.

Visual Studio

  • In Solution Explorer, right-click the project. Select Add > New Folder. Name the folder Models.
  • Right-click the Models folder and select Add > Class. Name the class TodoItem and select Add.
  • Replace the template code with the following code:

Visual Studio Code

  • Add a folder named Models.
  • Add a TodoItem class to the Models folder with the following code:

Visual Studio for Mac

  • Right-click the project. Select Add > New Folder. Name the folder Models.
  • Right-click the Models folder, and select Add > New File > General > Empty Class.
  • Name the class TodoItem, and then click New.
  • Replace the template code with the following code:

C#

namespace TodoApi.Models
{
    public class TodoItem
    {
        public long Id { get; set; }
        public string Name { get; set; }
        public bool IsComplete { get; set; }
    }
}

The Id property functions as the unique key in a relational database.

Model classes can go anywhere in the project, but the Models folder is used by convention.

Add a database context

The database context is the main class that coordinates Entity Framework functionality for a data model. This class is created by deriving from the Microsoft.EntityFrameworkCore.DbContext class.

Visual Studio

Right-click the Models folder and select Add > Class. Name the class TodoContext and click Add.

Visual Studio Code/ Visual Studio for Mac

Add a TodoContext class to the Models folder.

Replace the template code with the following code:

C#

using Microsoft.EntityFrameworkCore;

namespace TodoApi.Models
{
    public class TodoContext : DbContext
    {
        public TodoContext(DbContextOptions<TodoContext> options)
            : base(options)
        {
        }

        public DbSet<TodoItem> TodoItems { get; set; }
    }
}

Register the database context

In ASP.NET Core, services such as the DB context must be registered with the dependency injection (DI) container. The container provides the service to controllers.

Update Startup.cs with the following highlighted code:

C#

// Unused usings removed
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using TodoApi.Models;

namespace TodoApi
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the 
        //container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<TodoContext>(opt =>
                opt.UseInMemoryDatabase("TodoList"));
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
        }

        // This method gets called by the runtime. Use this method to configure the HTTP 
        //request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                // The default HSTS value is 30 days. You may want to change this for 
                // production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }

            app.UseHttpsRedirection();
            app.UseMvc();
        }
    }
}

The preceding code:

  • Removes unused using declarations.
  • Adds the database context to the DI container.
  • Specifies that the database context will use an in-memory database.

Add a controller

Visual Studio

  • Right-click the Controllers folder.
  • Select Add > New Item.
  • In the Add New Item dialog, select the API Controller Class template.
  • Name the class TodoController, and select Add.
  • Create a web API with ASP.NET Core MVC

Visual Studio Code/ Visual Studio for Mac

In the Controllers folder, create a class named TodoController.

Replace the template code with the following code:

C#

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

namespace TodoApi.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class TodoController : ControllerBase
    {
        private readonly TodoContext _context;

        public TodoController(TodoContext context)
        {
            _context = context;

            if (_context.TodoItems.Count() == 0)
            {
                // Create a new TodoItem if collection is empty,
                // which means you can't delete all TodoItems.
                _context.TodoItems.Add(new TodoItem { Name = "Item1" });
                _context.SaveChanges();
            }
        }
    }
}

The preceding code:

  • Defines an API controller class without methods.
  • Decorates the class with the [ApiController] attribute. This attribute indicates that the controller responds to web API requests. For information about specific behaviors that the attribute enables, see Create web APIs with ASP.NET Core.
  • Uses DI to inject the database context (TodoContext) into the controller. The database context is used in each of the CRUD methods in the controller.
  • Adds an item named Item1 to the database if the database is empty. This code is in the constructor, so it runs every time there's a new HTTP request. If you delete all items, the constructor creates Item1 again the next time an API method is called. So it may look like the deletion didn't work when it actually did work.

Add Get methods

To provide an API that retrieves to-do items, add the following methods to the TodoController class:

C#

// GET: api/Todo
[HttpGet]
public async Task<ActionResult<IEnumerable<TodoItem>>> GetTodoItems()
{
    return await _context.TodoItems.ToListAsync();
}

// GET: api/Todo/5
[HttpGet("{id}")]
public async Task<ActionResult<TodoItem>> GetTodoItem(long id)
{
    var todoItem = await _context.TodoItems.FindAsync(id);

    if (todoItem == null)
    {
        return NotFound();
    }

    return todoItem;
}

These methods implement two GET endpoints:

  • GET /api/todo
  • GET /api/todo/{id}

Test the app by calling the two endpoints from a browser. For example:

  • [https://localhost:<port>/api/todo](https://localhost:<port>/api/todo)
  • [https://localhost:<port>/api/todo/1](https://localhost:<port>/api/todo/1)

The following HTTP response is produced by the call to GetTodoItems:

**JSON**

[
  {
    "id": 1,
    "name": "Item1",
    "isComplete": false
  }
]

Routing and URL paths

The [[HttpGet]](https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.httpgetattribute) attribute denotes a method that responds to an HTTP GET request. The URL path for each method is constructed as follows:

  • Start with the template string in the controller's Route attribute:

C#

namespace TodoApi.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class TodoController : ControllerBase
    {
        private readonly TodoContext _context;
  • Replace [controller] with the name of the controller, which by convention is the controller class name minus the "Controller" suffix. For this sample, the controller class name is TodoController, so the controller name is "todo". ASP.NET Core routing is case insensitive.
  • If the [HttpGet] attribute has a route template (for example, [HttpGet("products")]), append that to the path. This sample doesn't use a template. For more information, see Attribute routing with Http[Verb] attributes.

In the following GetTodoItem method, "{id}" is a placeholder variable for the unique identifier of the to-do item. When GetTodoItem is invoked, the value of "{id}" in the URL is provided to the method in itsid parameter.

C#

// GET: api/Todo/5
[HttpGet("{id}")]
public async Task<ActionResult<TodoItem>> GetTodoItem(long id)
{
    var todoItem = await _context.TodoItems.FindAsync(id);

    if (todoItem == null)
    {
        return NotFound();
    }

    return todoItem;
}

Return values

The return type of the GetTodoItems and GetTodoItem methods is ActionResult<T> type. ASP.NET Core automatically serializes the object to JSON and writes the JSON into the body of the response message. The response code for this return type is 200, assuming there are no unhandled exceptions. Unhandled exceptions are translated into 5xx errors.

ActionResult return types can represent a wide range of HTTP status codes. For example, GetTodoItem can return two different status values:

  • If no item matches the requested ID, the method returns a 404 NotFound error code.
  • Otherwise, the method returns 200 with a JSON response body. Returning item results in an HTTP 200 response.

Test the GetTodoItems method

This tutorial uses Postman to test the web API.

  • Install Postman
  • Start the web app.
  • Start Postman.
  • Disable SSL certificate verification
  • From File > Settings (*General tab), disable SSL certificate verification.
  • Warning
  • Re-enable SSL certificate verification after testing the controller.
  • Create a new request.
  • Set the HTTP method to GET.
  • Set the request URL to [https://localhost:<port>/api/todo](https://localhost:<port>/api/todo). For example, [https://localhost:5001/api/todo](https://localhost:5001/api/todo).
  • Set Two pane view in Postman.
  • Select Send.

Create a web API with ASP.NET Core MVC

Add a Create method

Add the following PostTodoItem method:

C#

	// POST: api/Todo
[HttpPost]
public async Task<ActionResult<TodoItem>> PostTodoItem(TodoItem item)
{
    _context.TodoItems.Add(item);
    await _context.SaveChangesAsync();

    return CreatedAtAction(nameof(GetTodoItem), new { id = item.Id }, item);
}
	```

The preceding code is an HTTP POST method, as indicated by the [[HttpPost]](https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.httppostattribute) attribute. The method gets the value of the to-do item from the body of the HTTP request.

The `CreatedAtAction` method:

*   Returns an HTTP 201 status code, if successful. HTTP 201 is the standard response for an HTTP POST method that creates a new resource on the server.
*   Adds a `Location` header to the response. The `Location` header specifies the URI of the newly created to-do item. For more information, see [10.2.2 201 Created](https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html).
*   References the `GetTodoItem` action to create the `Location` header's URI. The C# `nameof` keyword is used to avoid hard-coding the action name in the `CreatedAtAction` call.
*   C#

// GET: api/Todo/5
[HttpGet("{id}")]
public async Task<ActionResult<TodoItem>> GetTodoItem(long id)
{
var todoItem = await _context.TodoItems.FindAsync(id);

if (todoItem == null)
{
    return NotFound();
}

return todoItem;

}


### Test the PostTodoItem method

*   Build the project.
*   In Postman, set the HTTP method to `POST`.
*   Select the **Body** tab.
*   Select the **raw** radio button.
*   Set the type to **JSON (application/json)**.
*   In the request body enter JSON for a to-do item:
*   JSON

{

"name":"walk dog",
"isComplete":true
}
```

  • Select Send.
    Create a web API with ASP.NET Core MVC
  • If you get a 405 Method Not Allowed error, it's probably the result of not compiling the project after adding the PostTodoItem method.

Test the location header URI

  • Select the Headers tab in the Response pane.
  • Copy the Location header value:
    Create a web API with ASP.NET Core MVC
  • Set the method to GET.
  • Paste the URI (for example, [https://localhost:5001/api/Todo/2](https://localhost:5001/api/Todo/2))
  • Select Send.

Add a PutTodoItem method

Add the following PutTodoItem method:

C#

	// PUT: api/Todo/5
[HttpPut("{id}")]
public async Task<IActionResult> PutTodoItem(long id, TodoItem item)
{
    if (id != item.Id)
    {
        return BadRequest();
    }

    _context.Entry(item).State = EntityState.Modified;
    await _context.SaveChangesAsync();

    return NoContent();
}
	```

`PutTodoItem` is similar to `PostTodoItem`, except it uses HTTP PUT. The response is [204 (No Content)](https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html). According to the HTTP specification, a PUT request requires the client to send the entire updated entity, not just the changes. To support partial updates, use [HTTP PATCH](https://docs.microsoft.com/dotnet/api/microsoft.aspnetcore.mvc.httppatchattribute).

If you get an error calling `PutTodoItem`, call `GET` to ensure there is an item in the database.

### Test the PutTodoItem method

This sample uses an in-memory database that must be initialed each time the app is started. There must be an item in the database before you make a PUT call. Call GET to insure there is an item in the database before making a PUT call.

Update the to-do item that has id = 1 and set its name to "feed fish":

`JSON`

  {
"ID":1,
"name":"feed fish",
"isComplete":true

}
```

The following image shows the Postman update:

Create a web API with ASP.NET Core MVC

Add a DeleteTodoItem method

Add the following DeleteTodoItem method:

C#

	// DELETE: api/Todo/5
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteTodoItem(long id)
{
    var todoItem = await _context.TodoItems.FindAsync(id);

    if (todoItem == null)
    {
        return NotFound();
    }

    _context.TodoItems.Remove(todoItem);
    await _context.SaveChangesAsync();

    return NoContent();
}
	```

The `DeleteTodoItem` response is [204 (No Content)](https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html).

### Test the DeleteTodoItem method

Use Postman to delete a to-do item:

*   Set the method to `DELETE`.
*   Set the URI of the object to delete, for example `[https://localhost:5001/api/todo/1](https://localhost:5001/api/todo/1)`
*   Select **Send**

The sample app allows you to delete all the items, but when the last item is deleted, a new one is created by the model class constructor the next time the API is called.

## Call the Web API with jQuery

In this section, an HTML page is added that uses jQuery to call the web api. jQuery initiates the request and updates the page with the details from the API's response.

Configure the app to [serve static files](https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.builder.staticfileextensions.usestaticfiles#Microsoft_AspNetCore_Builder_StaticFileExtensions_UseStaticFiles_Microsoft_AspNetCore_Builder_IApplicationBuilder_) and [enable default file mapping](https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.builder.defaultfilesextensions.usedefaultfiles#Microsoft_AspNetCore_Builder_DefaultFilesExtensions_UseDefaultFiles_Microsoft_AspNetCore_Builder_IApplicationBuilder_):

`C#`

public void Configure(IApplicationBuilder app, IHostingEnvironment env)

{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
// The default HSTS value is 30 days. You may want to change this for
// production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}

app.UseDefaultFiles();
app.UseStaticFiles();
app.UseHttpsRedirection();
app.UseMvc();

}
```

Create a wwwroot folder in the project directory.

Add an HTML file named index.html to the wwwroot directory. Replace its contents with the following markup:

HTML

	<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>To-do CRUD</title>
    <style>
        input[type='submit'], button, [aria-label] {
            cursor: pointer;
        }

        #spoiler {
            display: none;
        }

        table {
            font-family: Arial, sans-serif;
            border: 1px solid;
            border-collapse: collapse;
        }

        th {
            background-color: #0066CC;
            color: white;
        }

        td {
            border: 1px solid;
            padding: 5px;
        }
    </style>
</head>
<body>
    <h1>To-do CRUD</h1>
    <h3>Add</h3>
    <form action="javascript:void(0);" method="POST" onsubmit="addItem()">
        <input type="text" id="add-name" placeholder="New to-do">
        <input type="submit" value="Add">
    </form>

    <div id="spoiler">
        <h3>Edit</h3>
        <form class="my-form">
            <input type="hidden" id="edit-id">
            <input type="checkbox" id="edit-isComplete">
            <input type="text" id="edit-name">
            <input type="submit" value="Save">
            <a onclick="closeInput()" aria-label="Close">&#10006;</a>
        </form>
    </div>

    <p id="counter"></p>

    <table>
        <tr>
            <th>Is Complete</th>
            <th>Name</th>
            <th></th>
            <th></th>
        </tr>
        <tbody id="todos"></tbody>
    </table>

    <script src="https://code.jquery.com/jquery-3.3.1.min.js"
            integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
            crossorigin="anonymous"></script>
    <script src="site.js"></script>
</body>
</html>
	```

Add a **JavaScript** file named _site.js_ to the _wwwroot_ directory. Replace its contents with the following code:

`JavaScript`

const uri = "api/todo";

let todos = null;
function getCount(data) {
const el = $("#counter");
let name = "to-do";
if (data) {
if (data > 1) {
name = "to-dos";
}
el.text(data + " " + name);
} else {
el.text("No " + name);
}
}

$(document).ready(function() {
getData();
});

function getData() {
$.ajax({
type: "GET",
url: uri,
cache: false,
success: function(data) {
const tBody = $("#todos");

  $(tBody).empty();

  getCount(data.length);

  $.each(data, function(key, item) {
    const tr = $("<tr></tr>")
      .append(
        $("<td></td>").append(
          $("<input/>", {
            type: "checkbox",
            disabled: true,
            checked: item.isComplete
          })
        )
      )
      .append($("<td></td>").text(item.name))
      .append(
        $("<td></td>").append(
          $("<button>Edit</button>").on("click", function() {
            editItem(item.id);
          })
        )
      )
      .append(
        $("<td></td>").append(
          $("<button>Delete</button>").on("click", function() {
            deleteItem(item.id);
          })
        )
      );

    tr.appendTo(tBody);
  });

  todos = data;
}

});
}

function addItem() {
const item = {
name: $("#add-name").val(),
isComplete: false
};

$.ajax({
type: "POST",
accepts: "application/json",
url: uri,
contentType: "application/json",
data: JSON.stringify(item),
error: function(jqXHR, textStatus, errorThrown) {
alert("Something went wrong!");
},
success: function(result) {
getData();
$("#add-name").val("");
}
});
}

function deleteItem(id) {
$.ajax({
url: uri + "/" + id,
type: "DELETE",
success: function(result) {
getData();
}
});
}

function editItem(id) {
$.each(todos, function(key, item) {
if (item.id === id) {
$("#edit-name").val(item.name);
$("#edit-id").val(item.id);
$("#edit-isComplete")[0].checked = item.isComplete;
}
});
$("#spoiler").css({ display: "block" });
}

$(".my-form").on("submit", function() {
const item = {
name: $("#edit-name").val(),
isComplete: $("#edit-isComplete").is(":checked"),
id: $("#edit-id").val()
};

$.ajax({
url: uri + "/" + $("#edit-id").val(),
type: "PUT",
accepts: "application/json",
contentType: "application/json",
data: JSON.stringify(item),
success: function(result) {
getData();
}
});

closeInput();
return false;
});

function closeInput() {
$("#spoiler").css({ display: "none" });
}
```

A change to the ASP.NET Core MVCproject's launch settings may be required to test the HTML page locally:

  • Open Properties\launchSettings.json.
  • Remove the launchUrl property to force the app to open at index.html—the project's default file.

There are several ways to get jQuery. In the preceding snippet, the library is loaded from a CDN.

This sample calls all of the CRUD methods of the API. Following are explanations of the calls to the API.

Get a list of to-do items

The jQuery ajax function sends a GET request to the API, which returns JSON representing an array of to-do items. The success callback function is invoked if the request succeeds. In the callback, the DOM is updated with the to-do information.

JavaScript

	$(document).ready(function() {
  getData();
});

function getData() {
  $.ajax({
    type: "GET",
    url: uri,
    cache: false,
    success: function(data) {
      const tBody = $("#todos");

      $(tBody).empty();

      getCount(data.length);

      $.each(data, function(key, item) {
        const tr = $("<tr></tr>")
          .append(
            $("<td></td>").append(
              $("<input/>", {
                type: "checkbox",
                disabled: true,
                checked: item.isComplete
              })
            )
          )
          .append($("<td></td>").text(item.name))
          .append(
            $("<td></td>").append(
              $("<button>Edit</button>").on("click", function() {
                editItem(item.id);
              })
            )
          )
          .append(
            $("<td></td>").append(
              $("<button>Delete</button>").on("click", function() {
                deleteItem(item.id);
              })
            )
          );

        tr.appendTo(tBody);
      });

      todos = data;
    }
  });
}
	```

### Add a to-do item

The [ajax](https://api.jquery.com/jquery.ajax/) function sends a `POST` request with the to-do item in the request body. The `accepts` and `contentType` options are set to `application/json` to specify the media type being received and sent. The to-do item is converted to JSON by using [JSON.stringify](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify). When the API returns a successful status code, the `getData` function is invoked to update the HTML table.

`JavaScript`

function addItem() {

const item = {
name: $("#add-name").val(),
isComplete: false
};

$.ajax({
type: "POST",
accepts: "application/json",
url: uri,
contentType: "application/json",
data: JSON.stringify(item),
error: function(jqXHR, textStatus, errorThrown) {
alert("Something went wrong!");
},
success: function(result) {
getData();
$("#add-name").val("");
}
});
}
```

Update a to-do item

Updating a to-do item is similar to adding one. The url changes to add the unique identifier of the item, and the type is PUT.

JavaScript

	$.ajax({
  url: uri + "/" + $("#edit-id").val(),
  type: "PUT",
  accepts: "application/json",
  contentType: "application/json",
  data: JSON.stringify(item),
  success: function(result) {
    getData();
  }
});
	```

### Delete a to-do item

Deleting a to-do item is accomplished by setting the `type` on the AJAX call to `DELETE` and specifying the item's unique identifier in the URL.

`JavaScript`

$.ajax({

url: uri + "/" + id,
type: "DELETE",
success: function(result) {
getData();
}
});
```

Thanks for reading

If you liked this post, share it with all of your programming buddies!

Follow me on Facebook | Twitter

Learn More

The Complete ASP.NET MVC 5 Course

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

Build an app with ASPNET Core and Angular from scratch

Build a Basic Website with ASP.NET MVC and Angular

How to build RESTful APIs with ASP.NET Core

Build a CRUD App with ASP.NET MVC and Entity Framework

How to Build a REST API with ASP.NET Web API?

Build a REST API with ASP.NET Core 2.2

Build amazing web apps with ASP.NET Core 3.0

Overview of Blazor Grid Templates

Overview of Blazor Grid Templates
Originally published by Ed Charbeneau at https://www.telerik.com     
<p>Using a template in an application implies that you're creating a custom experience for your user by leveraging a component or framework you're working with. Because the Telerik UI for Blazor components are native, built from the ground up using the Blazor framework, it can tap directly in to Blazor's best features. Grid component templates can fully utilize the HTML, Razor, and components to completely customize the user experience.</p><p>In this article we'll see an overview of what templates are available and simple use cases. We'll use these as building blocks to see just how dynamic a Blazor grid can be when using templates for advanced ideas like custom editors and master-detail views.</p>

Template Types

<p>There are currently three types of templates available for the Blazor grid: column Template, Editor Template, and Row Template. Each has very specific uses and are powerful tools for adapting the grid to your specific needs. Let's start with a quick introduction to each template type.</p>

Column Template

<p>By default, the grid renders the value of the field in the column exactly as it's provided from the data source. We can override this behavior by using a column Template which allows us to take control over the rendering of the object within the column. The Template provides the entire object currently bound to the row in which the column exists, and this object is the template's context. Through the Template we can apply custom formatting, insert additional HTML and images, and display Razor Components using any value from the context.</p><pre class="ql-syntax" spellcheck="false"><TelerikGridColumn Field="@(nameof(SampleData.Name))" Title="Employee Name">    <Template>       Employee name is: @((context as SampleData).Name)    </Template> </TelerikGridColumn> </pre><p>The column Template is visible when the current row is not in edit mode. To customize the grid's editing experience we'll use the EditorTemplate.</p>

Editor Template

<p>The EditorTemplate is a template that bound to the editing context. The EditorTemplate defines the inline template or component that will be rendered when the user is editing the field. Although the EditorTemplate acts much like the column Template, it is only shown when the given row is in edit mode.</p><pre class="ql-syntax" spellcheck="false"><TelerikGridColumn [email protected](Employee.VacationDays) Title="Position">    <EditorTemplate>        @{            var employeeToUpdate = context as Employee;                       <KendoNumericTextBox Decimals="1" Format="#.0 days" Max="15" Min="0" Step="0.5m" Value="@employeeToUpdate.VacationDays" />        }    </EditorTemplate> </TelerikGridColumn> </pre><p>The column and editor templates give excellent control over column rendering in the grid. For even more control we can choose to use a row template and completely customize the grid.</p>

Row Template

<p>Unlike the previously mentioned templates, the RowTemplate spans the entire grid for all columns. The row template allows you to define custom rendering for the entire <tr> element for each record. It can be convenient if you want to use templates for most or all of the columns, as it requires less markup than setting individual templates for many columns.</p><p>Since the template isn't bound to a specific column, it can use the Context attribute of the RowTemplate to set the name of the context variable. Its type is the model type to which the grid is bound.</p><pre class="ql-syntax" spellcheck="false"><RowTemplate Context="employee">    <td>        <span>@employee.Id</span>    </td>    <td>        Hired on: @(String.Format("{0:dd MMM yyyy}", employee.HireDate))    </td> </RowTemplate> <TelerikGridColumns>    <TelerikGridColumn [email protected](SampleData.Name) Title="Employee Name" />    <TelerikGridColumn [email protected](SampleData.HireDate) Title="Hire Date" /> </TelerikGridColumns> </pre><p>Using the three template types we can tackle a wide variety of requirements. Let's look at how flexible the Telerik UI for Blazor Grid can be - what we can accomplish might just surprise you.</p>

Image Template

<p>We'll begin with a simple yet common scenario, embedding an image in a grid column. Let's assume we have a list of users that we need to manage a broad range of details for. It be nice to associate a face with a name, and with a column template we can do just that. Using a column template we can use one or many values from the currently bound item's properties to generate an image element and display an image directly in the column. In this example we'll assume that our product's images are stored on the server with a relative path of /images/, and each image file name corresponds to the productId.</p><p>Let's begin without a template to see how the grid is structured without customization.</p><pre class="ql-syntax" spellcheck="false"><TelerikGrid [email protected] Height="500">    <TelerikGridColumns>        <TelerikGridColumn [email protected](Product.ProductName) Title="Product Name"/>        <TelerikGridColumn [email protected](Product.UnitPrice) Title="Unit Price"/>    </TelerikGridColumns> </TelerikGrid>

@functions {
   public IEnumerable<Product> GridData { get; set; }
   
    protected override void OnInit() => GridData = ... //fetch data;
}
</pre><p class="ql-align-center"></p><p>Here we have a basic two column grid with just a text display of each Product Name and Unit Price. Using a template we can transform the Product Name column to display an image alongside the product name.</p><p>To access the template, the Product Name column needs to have a TelerikGridColumn component with matching begin/end tags. Inside the component we'll add a Template component which will define our custom rendering. Inside of the template we have access to the context object, this is the current Product in scope. A simple cast of context as Product will give us access to the proper type.</p><pre class="ql-syntax" spellcheck="false"><TelerikGridColumn [email protected](Product.ProductName) Title="Product Name">
   <Template>
       @{
           var product = context as Product;
       }
   </Template>
</TelerikGridColumn>
</pre><p>Now that we have our current Product we can render it how we see fit within the column. Let's add an HTML <img tag and create a path from the ProductId property. We can apply CSS to the image using standard HTML markup class="rounded-circle". Also, since this is Razor, C# string literals are a valid way of formating the path src="@($"/images/{product.ProductId}.jpg")". We'll also display the Product Name property along side the image using simple markup.</p><pre class="ql-syntax" spellcheck="false"><TelerikGrid [email protected] Height="500">
   <TelerikGridColumns>
       <TelerikGridColumn [email protected](Product.ProductName) Title="Product Name">
           <Template>
               @{
                   var product = context as Product;
                   <img class="rounded-circle" src="@($"/images/{product.ProductId}.jpg")" />
                   <span>@product.ProductName</span>
               }
           </Template>
       </TelerikGridColumn>
       <TelerikGridColumn [email protected](Product.UnitPrice) Title="Unit Price"/>
   </TelerikGridColumns>
</TelerikGrid>

@functions ...
</pre><p class="ql-align-center"></p><p>Because the underlying Razor Components framework supports templates and the Telerik UI for Blazor Grid is built using the framework's native architecture, the grid is a fully capable solution to many problems.</p>

Custom Form

<p>With templates we can fully utilize Blazor's framework features. Inside the template we can add components, logic, and even trigger events. In addition, templates aren't just scoped to the component they're contained in - we can access events and values outside of the template as well. This opens up new possibilities for creating a custom experience.</p><p>Let's assume we want to create a custom edit experience versus using one of the built in grid editors. This will give us full control over every aspect of the form. The challenge is getting the form to interact with the grid. To make a custom editor we'll need to select an item, place its properties on a form, and save/cancel changes. On the surface this might seem like a complex task, however the framework has extremely flexible data binding mechanics.</p><p>Identifying the currently selected object would provide most of what we need to accomplish the task since we can bind its properties directly to form elements. The grid's template gives us access to items that are bound to a grid row, all we'll need is a method of selecting the value and creating a reference to the object. Let's start by creating a placeholder for our object reference using a field named selectedProduct. To create an easy way of selecting a product, a column template with a button will suffice. When the button is clicked, we'll invoke an in-line function to set selectedProduct to the current context.</p><pre class="ql-syntax" spellcheck="false"><TelerikGridColumn [email protected](Product.ProductId) Title="Id">
   <Template>
       <TelerikButton Icon="edit" OnClick="@(=> selectedProduct = (Product)context)">Edit</TelerikButton>
   </Template>
</TelerikGridColumn>
</pre><p>With the data referenced we can now add a form to display the information and provide save and cancel actions. The form will exist outside of the grid, since the object reference is now scoped to the page we can place the form anywhere outside the grid. The form can be hidden or shown based on if an item is selected using a standard Razor @if block.</p><pre class="ql-syntax" spellcheck="false">@if (selectedProduct != null) {
       ...form
}
</pre><p>Saving and canceling the edit are also straightforward tasks now. We just need to create buttons with corresponding OnClick events. To cancel the edit, the selectedProduct reference is simply reset to null.</p><pre class="ql-syntax" spellcheck="false"><TelerikGrid [email protected] [email protected] Pageable="true" [email protected]>
   <TelerikGridColumns>
       <TelerikGridColumn [email protected](Product.ProductId) Title="Id">
           <Template>
               <TelerikButton Icon="edit" OnClick="@(
=> selectedProduct = (Product)context)">Edit</TelerikButton>
           </Template>
       </TelerikGridColumn>
       <TelerikGridColumn [email protected](Product.ProductName) Title="Product Name" />
       <TelerikGridColumn [email protected](Product.UnitPrice) Title="Unit Price" />
   </TelerikGridColumns>
</TelerikGrid>
<hr />
@if (selectedProduct != null)
{
   <div class="form-group ">
       <label class="control-label" for="productName">
           Product Name
       </label>
       <input class="form-control" bind="@selectedProduct.ProductName" id="name" name="name" type="text" />
   </div>
   <div class="form-group ">
       <label class="control-label" for="unitPrice">
           Unit Price
       </label>
       <input class="form-control" bind="@selectedProduct.UnitPrice" id="unitPrice" name="unitPrice" type="number" />
   </div>
   <div class="form-group">
       <div>
           <TelerikButton Icon="save" Class="k-primary" OnClick="@Save">Save</TelerikButton>
           <TelerikButton Icon="cancel" OnClick="@(_=> selectedProduct = null)">Cancel</TelerikButton>
       </div>
   </div>
}
@functions {
   ...
   Product selectedProduct;

   void Save()
   {
              // save logic
       selectedProduct = null;
   }
}
</pre><p class="ql-align-center"></p><p>With the ability to share state with other components on the page, the opportunities for template driven experiences are unlimited.</p>

Master-Detail View

<p>Using templates we can completely transform an entire grid row with custom HTML, Razor, and even components. In this next example we'll look at just how advanced we can get with templates by adding a Master-Detail view to a grid.</p><p>A likely scenario for any application is one where a data point has many properties with varying importance. Some of those properties should always be front and center, while others might be helpful to have just within reach. This is where a master-detail view can be quite handy. This type of view helps keep extended data out of view until it is requested by the user, while keeping critical data up front all of the time.</p><p>Using the RowTemplate we can define two different states for our row which can easily be toggled by a simple button click. We'll start with the default state which only displays two columns of data. This view is nicely tucked away in a custom component called ProductMasterTemplate and takes a parameter of Product to be displayed in a two column format.</p><pre class="ql-syntax" spellcheck="false"><ProductMasterTemplate Product="@product" />
</pre><p>HTML</p><p>In addition, we'll use a more complex view to reveal all of the data for a given product in a list view. Once again, we'll encapsulate the view in custom component called ProductDetailTemplate.</p><pre class="ql-syntax" spellcheck="false"><ProductDetailTemplate Product="@product"/>
</pre><p>Within each of these custom components are table data cells <td> that contain Razor code for displaying the properties of a given Product. The contents of the row template must be <td> elements and their number (or total colspan) must match the number of columns defined in the grid. Internally both templates contain markup similar to the following example.</p><pre class="ql-syntax" spellcheck="false"><td>@Product.property</td>
<td colspan="2">
       ... some view logic
</td>
</pre><p>With the two states clearly defined as components we can focus on switching between the two. Let's begin by defining which item is selected by creating a variable where we can hold a reference to the selected product. As such, we'll name it SelectedProduct. To enable the user to toggle between views, we'll need a set of buttons to display for the user. To show the details we'll simply check the SelectedProduct to see if it matches the current item in the row. Since we're using Blazor, we can easily set the state of SelectedProduct directly in the event handler with an in-line function, OnClick="@(=> SelectedProduct = ...)".</p><pre class="ql-syntax" spellcheck="false">   <RowTemplate Context="product">
       @if (SelectedProduct != product)
       {
           <td>
               <TelerikButton Icon="@IconName.Window" OnClick="@(
=> SelectedProduct = product)">Details</TelerikButton>
           </td>
           <ProductMasterTemplate Product="@product" />
       }
       else
       {
           <td>
               <TelerikButton  Icon="@IconName.Close" OnClick="@(=> SelectedProduct = null)">Close</TelerikButton>
           </td>
           <ProductDetailTemplate Product="@product"/>
       }
   </RowTemplate>
</pre><p>The completed code below is actually quite simple due to the combination of template and component architecture.</p><pre class="ql-syntax" spellcheck="false"><TelerikGrid [email protected] Height="@Height">
   <RowTemplate Context="product">
       @if (SelectedProduct != product)
       {
           <td>
               <TelerikButton Icon="@IconName.Window" OnClick="@(
=> SelectedProduct = product)">Details</TelerikButton>
           </td>
           <ProductMasterTemplate Product="@product" />
       }
       else
       {
           <td>
               <TelerikButton  Icon="@IconName.Close" OnClick="@(_=> SelectedProduct = null)">Close</TelerikButton>
           </td>
           <ProductDetailTemplate Product="@product"/>
       }
   </RowTemplate>
   <TelerikGridColumns>
       <TelerikGridColumn Width="100" [email protected](Product.ProductName) Title="Product" />
       <TelerikGridColumn [email protected](Product.ProductName) Title="Product Name" />
       <TelerikGridColumn [email protected](Product.UnitsInStock) Title="Unit Price" />
   </TelerikGridColumns>
</TelerikGrid>

@functions {
   Product SelectedProduct;
}
</pre><p>Clicking the Details button gives us a slick UI that allows us to drill into grid data.</p><p class="ql-align-center"></p>

Conclusion

<p>Because the Telerik UI for Blazor components are native, built from the ground up using the Blazor framework, it can tap directly in to Blazor's best features. Grid component templates can fully utilize the HTML, Razor, and components to completely customize the user experience. Simple templates are useful for formatting or displaying images, while more extensive templates can transform the user interface completely adding entirely new functionality to the grid.</p><p>In this post we focused on the grid, however other components like the DropDownList already feature template fields as well. Make sure you download the latest release and try the templates for yourself using our demo repository on GitHub.</p><p>Thanks for reading ❤</p><p>If you liked this post, share it with all of your programming buddies!</p><p>Follow us on Facebook | Twitter</p>

Further reading about Blazor

<p>☞ Blazor CRUD Using Google Cloud Firestore</p><p>☞ Blazor: A new framework for browser-based .NET Apps</p>

How to create an Angular 8 application with ASP.NET Core 3.0

How to create an Angular 8 application with ASP.NET Core 3.0

Introduction

Microsoft just released .NET Core 3.0 on 23rd September 2019. You can get the latest version from this URL. Please note, if you are a Windows developer, you must install Visual Studio 2019 version 16.3 or later to work with this version. .NET Core 3.0 contains more awesome features. Previous ASP.NET version 2.1 and 2.2 were shipped with Angular version 6 only. But in this current release, Microsoft added the latest version of Angular 8. They have resolved the loading issues in previous version as well. In this post, I will explain the steps to create an Angular 8 application with ASP.NET 3.0. We will create a simple controller class to get latest C# Corner posts details and will be shown in the home component. We will get more features soon from Microsoft soon.

Install Node.js latest version

Please download the latest version of Node.js from their website. You require Node.js 10 or later version to work with Angular 8 as per their official documentation.

How to create an Angular 8 application with ASP.NET Core

Download and Install .NET Core 3.0 SDK.

As I mentioned earlier, .NET Core 3.0 requires Visual Studio 2019 v.16.3 or later. Please download and install the latest version of Visual Studio.

After installing both .NET Core 3.0 and Visual Studio 2019 v.16.3, you can create a new project in Visual Studio.

How to create an Angular 8 application with ASP.NET Core

Choose ASP.NET Core Web Application template and click Next button.

How to create an Angular 8 application with ASP.NET Core

Please give a valid name to the project and choose an appropriate folder to save that project. Click “Create” button to go next stage.

How to create an Angular 8 application with ASP.NET Core

Please note, by default HTTPS configuration is selected. If you do not wish that, please remove the tick from check box.

After clicking the “Create” button, your new project will be created shortly.

How to create an Angular 8 application with ASP.NET Core

You can see a “ClientApp” folder is created in the project. This is our Angular 8 project.

How to create an Angular 8 application with ASP.NET Core

If you check the package.json file, you can see the Angular library references. Please note that, node_modules are not yet created automatically. You must build the solution to create node packages. Other option is to just run the project. The node dependencies will be created automatically.

How to create an Angular 8 application with ASP.NET Core

In previous version of Angular 6 with ASP.NET Core 2.2, showed some error in the startup needed multiple refresh to resolve the issue. In this version, Microsoft resolved those issues.

How to create an Angular 8 application with ASP.NET Core

But currently I am getting some errors in the console with default project. Hopefully, Microsoft team will resolve these issues in coming releases. Adding to this project, we can create a new controller for getting the latest posts details (articles, blogs and news) from C# Corner RSS feeds.

Create an API controller for getting C# Corner RSS Feeds

We can create a “Feed” class.


    using System;  
      
    namespace Angular8ASPNETCore3  
    {  
        public class Feed  
        {  
            public string Link { get; set; }  
            public string Title { get; set; }  
            public string FeedType { get; set; }  
            public string Author { get; set; }  
            public string Content { get; set; }  
            public DateTime PubDate { get; set; }  
            public string PublishDate { get; set; }  
      
            public Feed()  
            {  
                Link = "";  
                Title = "";  
                FeedType = "";  
                Author = "";  
                Content = "";  
                PubDate = DateTime.Today;  
                PublishDate = DateTime.Today.ToString("dd-MMM-yyyy");  
            }  
        }  
    }  

We can create the controller for getting RSS feeds for latest post details from C# Corner.

RssFeedsController.cs


    using Microsoft.AspNetCore.Mvc;  
    using System;  
    using System.Collections.Generic;  
    using System.Globalization;  
    using System.Linq;  
    using System.Xml.Linq;  
      
    namespace Angular8ASPNETCore3.Controllers  
    {  
        [ApiController]  
        [Route("[controller]")]  
        public class RssFeedsController : ControllerBase  
        {  
            readonly CultureInfo culture = new CultureInfo("en-US");  
      
            [HttpGet]  
            public IEnumerable<Feed> Get()  
            {  
                try  
                {  
                    XDocument doc = XDocument.Load("https://www.c-sharpcorner.com/rss/latestcontentall.aspx");  
                    var entries = from item in doc.Root.Descendants().First(i => i.Name.LocalName == "channel").Elements().Where(i => i.Name.LocalName == "item")  
                                  select new Feed  
                                  {  
                                      Content = item.Elements().First(i => i.Name.LocalName == "description").Value,  
                                      Link = (item.Elements().First(i => i.Name.LocalName == "link").Value).StartsWith("/") ? "https://www.c-sharpcorner.com" + item.Elements().First(i => i.Name.LocalName == "link").Value : item.Elements().First(i => i.Name.LocalName == "link").Value,  
                                      PubDate = Convert.ToDateTime(item.Elements().First(i => i.Name.LocalName == "pubDate").Value, culture),  
                                      PublishDate = Convert.ToDateTime(item.Elements().First(i => i.Name.LocalName == "pubDate").Value, culture).ToString("dd-MMM-yyyy"),  
                                      Title = item.Elements().First(i => i.Name.LocalName == "title").Value,  
                                      FeedType = (item.Elements().First(i => i.Name.LocalName == "link").Value).ToLowerInvariant().Contains("blog") ? "Blog" : (item.Elements().First(i => i.Name.LocalName == "link").Value).ToLowerInvariant().Contains("news") ? "News" : "Article",  
                                      Author = item.Elements().First(i => i.Name.LocalName == "author").Value  
                                  };  
      
                    return entries.OrderByDescending(o => o.PubDate);  
                }  
                catch  
                {  
                    List<Feed> feeds = new List<Feed>();  
                    Feed feed = new Feed();  
                    feeds.Add(feed);  
                    return feeds;  
                }  
            }  
        }  
    }  

Please create above class under “Controllers” folder and paste above code. Please add required references to your class.

We can modify the Home component inside the “ClientApp”, “src” and “app” folder with below code.

home.component.ts


    import { Component, Inject } from '@angular/core';  
    import { HttpClient } from '@angular/common/http';  
      
    @Component({  
        selector: 'app-home',  
        templateUrl: './home.component.html'  
    })  
    export class HomeComponent {  
        latestPosts: Feed[] = [];  
        constructor(http: HttpClient, @Inject('BASE_URL') baseUrl: string) {  
            http.get<Feed[]>(baseUrl + 'rssfeeds').subscribe(result => {  
                this.latestPosts = result;  
            }, error => console.error(error));  
        }  
    }  
      
    interface Feed {  
        link: string;  
        title: string;  
        feedType: string;  
        author: string;  
        content: string;  
        publishDate: string;  
    }    

Also modify the template file with below code.

home.component.html

<div style="text-align:center">  
  <h1 style="margin-top:10px;">  
    Welcome to Angular <b style="color:crimson">8</b> with ASP.NET Core <b style="color:navy">3.0</b>  
  </h1>  
  <img width="200" alt="Angular ASP.Net Core Logo" src="../assets/angularcore.png" />  
  <div class="card" style="margin-left:50px; margin-right:50px; margin-bottom:50px;">  
    <div class="card-header" style="font-weight:bold; font-size:x-large;">  
      C# Corner Latest Posts from RSS Feeds  
    </div>  
    <div class="card-body">  
      <div class="table-responsive" style="max-height:385px;">  
        <table class="table mb-0" *ngIf="latestPosts && latestPosts.length>0">  
          <thead>  
            <tr>  
              <th>Sl.No</th>  
              <th>Post Title(With Link)</th>  
              <th>Post Type</th>  
              <th>Published Date</th>  
              <th>Author</th>  
            </tr>  
          </thead>  
          <tbody>  
            <tr *ngFor="let post of latestPosts; let i = index">  
              <td>{{ i + 1 }}</td>  
              <td style="text-align:left;"><a href="{{post.link}}" target="_blank">{{post.title}}</a></td>  
              <td>{{ post.feedType }}</td>  
              <td>{{ post.publishDate }}</td>  
              <td>{{ post.author}} </td>  
            </tr>  
          </tbody>  
        </table>  
      </div>  
    </div>  
  </div>  
</div> 

We have successfully modified the Home component. We can run the application.

How to create an Angular 8 application with ASP.NET Core

We could see the latest 30 articles/blogs/news details from C# Croner in this home page.

Conclusion

In this post, we could see how to create an Angular 8 project with ASP.NET Core 3.0 latest SDK in very simple steps. We could also see that; Microsoft improved the performance of Angular 8 application and reduced the initial loading time as well. I can say this is very light weight build. We can expect more exciting features from Microsoft team very soon. I will also try to write more articles on other features of .NET Core 3.0 very soon. Please give your valuable feedback about this post.