How to send Email in ASP.NET Core-Beginner’s Guide

How to send Email in ASP.NET Core-Beginner’s Guide

This article explain how to send Email in ASP.NET Core using MailKit.  For this article we consider ASP.NET Core 5.0, at the end of this article you will have full depth idea about how we can easily integrate Email in ASP.NET Core. Also please follow our article about how to send SMS using ASP.NET Core.

Find Source code in GitHub- ASP.NET Core 5.0
Find Source Code in GitHub- ASP.NET Core 3.1

Now-a-days application will send emails in plain text, support attachments (multiple attachments at once) and also we will learn how to Send Branded Emails using HTML Templates. Note that we will be using Mailkit to send the emails. This is what Microsoft recommends over the standard SMTPClient class.

What is MailKit ?

MailKit is an open-source cross-platform library that can be used in .NET or .NET Core applications running on Windows, Linux, or Mac. MailKit is a more like email clients of SMTP server. The SMTP server will have an address that will be used by email clients to send emails in ASP.NET Core. Based on the SMTP email server being used to send mails you will have to obtain server details like Host, Port, etc., and configure the same in your application.

What is SMTP Server ?

SMTP(Simple Mail Transfer Protocol) server are email based application servers that allow you to send and receive mails between senders & receivers. For e.g. Gmail is an SMTP server. On registering for email service these servers provided email id account using which we can send/receive emails on that SMTP Server.

What are going to discuss in this Post ?

In this post we are going to create examples of

  1. Send Email with Attachments
  2. Send Email With Custom Template

Creating ASP.NET Core Project and Implement Email Configuration

Let’s create a .NET Core Web API project considering ASO.NET Core 5.0 with selecting ASP.NET Core Web API.

Tick on Enable OpenAPI Support that enables SWAGGER into .NET Core API Project.

What is Swagger ?

Swagger is an Interface Description Language for describing RESTful APIs expressed using JSON. Swagger is used together with a set of open-source software tools to design, build, document, and use RESTful web services. Swagger includes automated documentation, code generation, and test-case generation

Add MailKit Nuget package to ASP.NET Core Project

Add SMTP Server & Email Account details in appsettings.json file

To send an email we need SMTP server which will connect to server to send emails. Also to access this SMTP server we will need security credentials to access that server i.e. details of the Email Account which has been created on that server to send emails will be required. Now, these details should not be hardcoded in code as these are configurable parameters that can change over time so we will store the above details in the appsettings.json file.

User Id & Password of the SMTP Server is very sensitive data and should not be stored in plain text in the appsettings.json file as it can be viewed by any person who has access to code or deployment environments. Instead, it should be securely stored somewhere so that it can be accessed only by unauthorized persons.

For demonstration purposes password is being stored in the appsettings.json file.

"EmailSettings": {
    "EMail": "corespiderpro@gmail.com",
    "Name": "CoreSpider-The Knowledge Hub",
    "Password": "**********",
    "Host": "smtp.gmail.com",
    "Port": 587
  }

As you see we use Gmail ID as SMTP server. For security I have made *** as Password, you can set your original Gmail password to set Gmail as SMTP ready.

Quick Tip to Secure Sensitive Data

During Development, It is advisable to add data that is to be kept private on to the appsettings.Development.Json. This file is generated while setting the Environment Variable to Development. While adding the project to source control, you can exclude the appsettings.Development.json, so that GIT ignores the file and does not commit it to the main repository. In this way, we can have a good separation of confidential information from the outside world.

Configure Gmail SMTP Server

To configure Gmail SMTP follow these steps.

Developers usually prefer using the GMAIL SMTP server for production and testing purposes, as it is quite easy and reliable too. Gmail allows you to send 2,000 emails per day using the Gmail SMTP Server for FREE. That’s pretty much to get started, right?

Here is what you will need to use Gmail SMTP.

  • Regarding Gmail ID (Do not use a personal Email ID, quite risky if compromised.)
  • The Password.
  • Host or SMTP Server address – If you are going with Gmail, use smtp.gmail.com
  • Port – Use 465 (SSL) or 587 (TLS)

After you get the details, we will need to allow your Gmail account to send emails using external (less- secure applications). To enable this, go to https://myaccount.google.com/security and turn ON Less Secure App Access.

Access the Appsettings.json file

To access the appsettings.json file we need to create a Settings folder inside our ASP.NET Core Web API project. And create a class with name as EmailSettings.

 public class EmailSettings
    {
        public string EMail { get; set; }
        public string Name { get; set; }
        public string Password { get; set; }
        public string Host { get; set; }
        public int Port { get; set; }
    }

We have the data in appsettings.json file. How do we transfer these data to an instance of EmailSettingsat runtime ? IOptions and Dependency Injection to the rescue. Navigate to Starup/ConfigureServices Method and add the following line.

services.Configure<EmailSettings>(Configuration.GetSection("EmailSettings"));

Declaring the Model that hold Email Information’s

Let’s create a Model class holds the Email Information that responsible to send email with attachments. Create another model class that hold the information of Email and UserName that is responsible with templates.

  public class EmailInfo
    {
        public string EmailTo { get; set; }
        public string Subject { get; set; }
        public string Body { get; set; }
        public List<IFormFile> Attachments { get; set; }
    }
  public class EmailSource
    {
        public string EmailTo { get; set; }
        public string UserName { get; set; }
    }

Create a Interface that responsible to Send Email

Let’s create a Interface inside Services folder with declaring two methods.

public interface IEmailService
    {
        Task SendEmailAsync(EmailInfo emailInfo);
        Task SendEmailTemplateAsync(EmailSource emailSource);
    }

Create a Concrete class that implement Interface

We will have a method that takes in the EmailInfo object and sends the email. Next, Add a concrete class that will implement this interface. Services/EmailService.cs

 public class EmailService : IEmailService
    {
        private readonly EmailSettings _mailSettings;
        public EmailService(IOptions<EmailSettings> mailSettings)
        {
            _mailSettings = mailSettings.Value;
        }
        public async Task SendEmailAsync(EmailInfo emailInfo)
        {
            var email = new MimeMessage();
            email.Sender = MailboxAddress.Parse(_mailSettings.EMail);
            email.To.Add(MailboxAddress.Parse(emailInfo.EmailTo));
            email.Subject = emailInfo.Subject;
            var builder = new BodyBuilder();
            if (emailInfo.Attachments != null)
            {
                byte[] fileBytes;
                foreach (var file in emailInfo.Attachments)
                {
                    if (file.Length > 0)
                    {
                        using (var ms = new MemoryStream())
                        {
                            file.CopyTo(ms);
                            fileBytes = ms.ToArray();
                        }
                        builder.Attachments.Add(file.FileName, fileBytes, ContentType.Parse(file.ContentType));
                    }
                }
            }
            builder.HtmlBody = emailInfo.Body;
            email.Body = builder.ToMessageBody();
            using var smtp = new SmtpClient();
            smtp.Connect(_mailSettings.Host, _mailSettings.Port, SecureSocketOptions.StartTls);
            smtp.Authenticate(_mailSettings.EMail, _mailSettings.Password);
            await smtp.SendAsync(email);
            smtp.Disconnect(true);
        }

        public async Task SendEmailTemplateAsync(EmailSource emailSource)
        {
            string FilePath = Directory.GetCurrentDirectory() + "\\Templates\\CustomTemplate.html";
            StreamReader str = new StreamReader(FilePath);
            string MailText = str.ReadToEnd();
            str.Close();
            MailText = MailText.Replace("[username]", emailSource.UserName).Replace("[email]", emailSource.EmailTo);
            var email = new MimeMessage();
            email.Sender = MailboxAddress.Parse(_mailSettings.EMail);
            email.To.Add(MailboxAddress.Parse(emailSource.EmailTo));
            email.Subject = $"Welcome {emailSource.UserName}";
            var builder = new BodyBuilder();
            builder.HtmlBody = MailText;
            email.Body = builder.ToMessageBody();
            using var smtp = new SmtpClient();
            smtp.Connect(_mailSettings.Host, _mailSettings.Port, SecureSocketOptions.StartTls);
            smtp.Authenticate(_mailSettings.EMail, _mailSettings.Password);
            await smtp.SendAsync(email);
            smtp.Disconnect(true);
        }

    }

Code Explanation

Here we Injecting the IOptions<EmailSettings> to the constructor and assigning it’s value to the instance of EmailSettings. Like this, we will be able to access the data from the JSON at runtime.

SendEmailAsync

  • The basic idea is to create an object of MimeMessage (a class from Mimekit ) and send it using a SMTPClient instance (Mailkit).
  • Here we create new object of MimeMessage and adds in the Sender, To Address and Subject to this object. We will be filling the message related data (subject, body) from the mailRequest and the data we get from our JSON File.
  • If there are any attachments (files) in the request object, we transform the file to an attachment and add it to the mail message as an Attachment Object of Body Builder.
  • Send the Message using the SMTP SendMailAsync Method.

SendEmailTemplateAsync

  • We get the file path of our welcome template and read the file as a string. ( We create a HTML template name as CustomTemplate.html) inside “\Templates\CustomTemplate.html”.
  • Now, We replace the username and email tag with the actual data and here we adds a default subject
  • Set the body of the email from the template string and send email using SMTP SendAsync.

Add the Dependency Injection Service in startup.cs

services.AddTransient<IEmailService, EmailService>();

Create controller to send the Email

Let’s create a controller name as EmailController and here we call the service class.

 [Route("api/[controller]")]
    [ApiController]
    public class EmailController : ControllerBase
    {
        private readonly IEmailService mailService;
        public EmailController(IEmailService mailService)
        {
            this.mailService = mailService;
        }
        [HttpPost("sendEmail")]
        public async Task<IActionResult> SendMail([FromForm] EmailInfo emailInfo)
        {
            try
            {
                await mailService.SendEmailAsync(emailInfo);
                return Ok();
            }
            catch (Exception ex)
            {
                throw;
            }
        }
        [HttpPost("sendEmailTemplate")]
        public async Task<IActionResult> SendWelcomeMail([FromForm] EmailSource source)
        {
            try
            {
                await mailService.SendEmailTemplateAsync(source);
                return Ok();
            }
            catch (Exception ex)
            {
                throw;
            }
        }
    }

Code Explanation

  • We make constructor Injection inside EmailController.
  • And we make [HttpPost(“sendEmail”)] that responsible to send email with attachments.
  • And we make [HttpPost(“sendEmailTemplate”)] that responsible to send email with templates.

Now we are ready ! All the configurations has been done and now we ready to test the Email using Swagger API.

Send Email – (Testing With Swagger)

Let’s build the application and run the project and as SWAGGER is already is configured while we create the project and select the Enable Open API Support.

Test Email with Attachment

To use email with attachment, add the email Id where we are going to sent email with Subject and Body. Here we added 3 attachments and then click on Execute button to send the email.

Let’s open the Gmail account and we can clearly seen that the Gmail SMTP work perfectly.

Test Email with Custom Template

We already create a custom HTML file inside Templates folder. Let’s using swagger we can test the email with templates file considering Email and UserName.

Let’s check the Gmail and we can see the Email with template

Source Code

Find Source code in GitHub- ASP.NET Core 5.0
Find Source Code in GitHub- ASP.NET Core 3.1

Summary

In this article, We covered all that is needed to Send Emails with ASP.NET Core. You can find source code in ASP.NET Core 5.0 and 3.1. Share your comments and suggestions about this article in the comments section below.

Have you enjoyed this post and found it useful? If so, please consider supporting me:

Buy me a coffeeBuy me a coffee

Latest Post

ASP.NET Core Web API with MongoDB CRUD- Beginner’s Guide
ASP.NET CORE WEB API 5.0 MONGODB CRUD

This article explain CRUD operation using MongoDB in ASP.NET Core Web API. We discuss here basics of MongoDB and how Read more

CRUD Operation in ASP.NET Web API with Entity Framework
CRUD-Operation-in-asp.net-Web-api

This blog explain CRUD Operation in ASP.NET Web API with Entity framework and then the web API check using POSTMAN Read more

Deploy ASP.NET Core Web App in Azure Virtual Machine
Deploy ASP.NET Core Web App in Azure Virtual Machine

This article explain about Deploy ASP.NET Core Web App in Azure Virtual Machine. We discuss here how to create VM Read more

Toast Notifications in ASP.NET Core Razor Pages
Toast Notifications in ASP.NET Core Razor Pages

This article we will learn how simply we can use Toast Notifications in ASP.NET Core Razor Pages 5.0. Mainly on Read more

Toast Notifications in ASP.NET Core Razor Pages

Toast Notifications in ASP.NET Core Razor Pages

In this article we will learn how simply we can use Toast Notifications in ASP.NET Core Razor Pages 5.0. Mainly on the MEAN stack project, we require to notify the end-user based on events. toastr.js library is very simple and easy to use. Importantly in today’s world of responsive sites, these notification are also responsive. Please follow our previous article Worker Service in .NET Core

Find the Source Code

What is Toastr ?

Toastr is a simple JavaScript toast notification library that is small, easy to use, and extendable. It allows you to create simple toasts with HTML5 and JavaScript like this: Simply include the files in your HTML page and write a simple line of code like this: toastr.

Simply include the files in your HTML page and write a simple line of code like this:

toastr.success(new Date(), 'Current Day & Time');




How to use Toast in ASP.NET Core Razor Pages ?

  • Create a ASP.NET Core Razor page application and use toast like below.
  • Add the below html in Index page.
@page
@model IndexModel
@{
    ViewData["Title"] = "Home page";
}

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js">
    </script>
    <script type="text/javascript" src="js/toastr.js">
    </script>
    <link rel="stylesheet" type="text/css" href="css/toastr.css">
    <script type="text/javascript" src="js/toastrsample.js"></script>
    <link rel="stylesheet" type="text/css" href="css/toastrsample.css">
    <title>Use Toastr in ASP .NET Core-5</title>
</head>
<body>
    <h2>
        How to Use Toastr Notifications
    </h2>
    <div class="control-group" id="toastrTypeGroup">
        <div class="controls">
            <label>
                Toast Type
            </label>
            <label class="radio">
                <input type="radio" name="toasts" value="success" checked />Success
            </label>
            <label class="radio">
                <input type="radio" name="toasts" value="info" />Info
            </label>
            <label class="radio">
                <input type="radio" name="toasts" value="warning" />Warning
            </label>
            <label class="radio">
                <input type="radio" name="toasts" value="error" />Error
            </label>
        </div>
    </div>
    <br />
    <div class="control-group" id="toastrPositionGroup">
        <div class="controls">
            <label>
                Position
            </label>
            <label class="radio">
                <input type="radio" name="positions" value="toast-top-right" checked />Top Right
            </label>
            <label class="radio">
                <input type="radio" name="positions" value="toast-bottom-right" />Bottom Right
            </label>
            <label class="radio">
                <input type="radio" name="positions" value="toast-bottom-left" />Bottom Left
            </label>
            <label class="radio">
                <input type="radio" name="positions" value="toast-top-left" />Top Left
            </label>
            <label class="radio">
                <input type="radio" name="positions" value="toast-top-full-width" />Top Full Width
            </label>
            <label class="radio">
                <input type="radio" name="positions" value="toast-bottom-full-width" />Bottom Full Width
            </label>
            <label class="radio">
                <input type="radio" name="positions" value="toast-top-center" />Top Center
            </label>
            <label class="radio">
                <input type="radio" name="positions" value="toast-bottom-center" />Bottom Center
            </label>
        </div>
    </div>
    <br />
    <button type="button" class="btn" id="showtoast" class="btn btn-primary">
        Show Toastr Notification
    </button>
</body>
</html>   

  • Create JavaScript file (toastrsample.js)
$(function()    
  {    
    $('#showtoast').click(function()    
       {    
        toastr.options =     
          {    
            "debug": false,    
            "positionClass": $("#toastrPositionGroup input:radio:checked").val(),    
            "onclick": null,    
            "fadeIn": 300,    
            "fadeOut": 100,    
            "timeOut": 3000,    
            "extendedTimeOut": 1000    
        }    
        var d = Date();    
        toastr[$("#toastrTypeGroup input:radio:checked").val()](d, "Current Day & Time");    
    });    
});  

Run the application and see the output like below.

Source Code

Find Source Code

Summary

So far in this article we discuss how to use Toast Notifications in ASP.NET Core Razor Pages. If have any suggestion for improvement for this article then please feel to write to us. Below points we are discuss in this article.

Buy me a coffeeBuy me a coffee

Integrate Razorpay Payment Gateway in ASP.NET Core
Integrate Razorpay Payment Gateway in ASP.NET Core

This article explain about Integrate Razorpay Payment Gateway in ASP.NET Core. We discuss here how to implement Razorpay gateway in Read more

Deploy ASP.NET Core Web App in Azure Virtual Machine
Deploy ASP.NET Core Web App in Azure Virtual Machine

This article explain about Deploy ASP.NET Core Web App in Azure Virtual Machine. We discuss here how to create VM Read more

ASP.NET Core Web API with MongoDB CRUD- Beginner’s Guide
ASP.NET CORE WEB API 5.0 MONGODB CRUD

This article explain CRUD operation using MongoDB in ASP.NET Core Web API. We discuss here basics of MongoDB and how Read more

How to send Email in ASP.NET Core-Beginner’s Guide
How to send Email in ASP.NET Core

This article explain how to send Email in ASP.NET Core using Mailkit. It is open-source cross-platform library that can be Read more

Build CRUD REST APIs with ASP.NET Core 5.0 with EF Core 5.0

Build CRUD REST APIs with ASP.NET Core 5.0 with EF Core 5.0

This article explains how to build CRUD REST APIs with ASP.NET Core 5.0 with Entity Framework 5.0 code first approach. Also we learn how to secure APIs using JWT authentication token and test the CRUD APIs using POSTMAN. Please have a look our previous article Migrate from ASP.NET Core 3.1 to 5.0- Beginners guide.

Find the source code

Prerequisites

–  Visual Studio 2019 16.8 or later
.NET 5.0 SDK
– SQL Server 2014 (You can use higher version of SQL)
– Postman to test API
Build CRUD REST APIs with ASP.NET Core 5.0 with EF Core 5.0
Tweet

What is REST API ?

REST stands for representational state transfer. REST APIs are the HTTP-based protocol that provides to communicate with other application using lightweight JSON format. As you know in current era there is no. of clients (mobile apps, browser-based SPAs, desktop apps, IOT apps, etc.), we need better ways for transferring data from servers to clients, independent of technology and server stacks. In this case REST API is the good benchmark among the application.

What is JWT Token ?

JWT stands for JSON Web Token, It is open standard and transfer data securely between two entities (client and server). A JWT is digitally signed using a secret key by a token provider or authentication server. A JWT helps the resource server verify the token data using the same secret key, so that you can trust the data.

JWT consists of the following three parts:

Header: encoded data of token type and the algorithm used to sign the data.

Payload: encoded data of claims intended to share.

Signature: created by signing (encoded header + encoded payload) using a secret key.

The final JWT token will be like this: Header.Payload.Signature. In below we described how JWT works.

Step 1: Client requesting token

The client sends a request to the authentication server with the necessary information like username and password to prove its identity. If the credential is valid then the server create a token with the necessary claims, and a JWT token will be sent back to the client.

Step 2: Client sends token to resource server

Client Stores the token temporarily and for each request to Resource or the API server, the client needs to include a token in the header and request the resource using its URI. Then the Server access the token decode and validate it.

Step 3: Resource server verifies the token

To verify the token below are the few steps.

  • Read the token from authentication header then Split the header, payload and signature from token.
  • Create signature of received header and payload using the same secret key used when creating the token.
  • Check whether both newly created signature and signature received from token are valid.
  • If the signatures are the same, the tokens are valid (not altered in the middle) and they provide access to the requested resource.
  • If the signatures are different, an unauthorized response will be sent back to the client. (In the middle, if claims are alerted, they will generate a different signature, hence resource access will be restricted.)

Create an ASP.NET Core 5.0 REST API application

To create an ASP.NET Core 5.0 Rest API application follow below steps.

  • Open Visual Studio 2019, Create New Project
  • Choose ASP.NET Core Web Application and then set Project location and project path.
  • Select ASP.NET Core SDK 5.0 and then select ASP.NET Core Web API project.

Install required Nuget Packages

Install below required packages using package manager console or you can install using Manage Nuget packages.

Install-Package Microsoft.EntityFrameworkCore-Version 5.0.0
Install-Package Microsoft.EntityFrameworkCore.Sqlite-Version 5.0.0
Install-Package Microsoft.EntityFrameworkCore.SqlServer-Version 5.0.0
Install-Package Microsoft.EntityFrameworkCore.SqlServer.Design-Version 1.1.6
Install-Package Microsoft.EntityFrameworkCore.Tools-Version 5.0.0
Install-Package Microsoft.VisualStudio.Web.CodeGeneration.Design-Version 5.0.0

Creating the Model Class

To do EF core 5.0 we do create the model class that treated as entity of product object and user object that should be done database operations. Right click on the Models folder and add the class name with following properties.

Product.cs

[Table("Products")]
    public class Product
    {
        [Key]
        public int ProductId { get; set; }
        public string Name { get; set; }
        public string Category { get; set; }
        [Column(TypeName = "decimal(18,2)")]
        public decimal Price { get; set; }
        public int Quantity { get; set; }
        [DatabaseGenerated(DatabaseGeneratedOption.Computed)]
        public DateTime CreateDate { get; set; }
    }
  • The product model consist the object of product information.
  • [Table(“Products”)] is belong to System.ComponentModel.DataAnnotations.Schema namespace. Here Products is the table name that we want to create dynamically using EF code first.
  • ProductId is the primary key of the table object.
  • Price column is set as default value.
  • CreateDate column is the computed value means it set as default date for this field.

User.cs

[Table("Users")]
    public class User
    {
        public int UserId { get; set; }
        public string FullName { get; set; }
        public string UserName { get; set; }
        public string Password { get; set; }
        public string Email { get; set; }
        [DatabaseGenerated(DatabaseGeneratedOption.Computed)]
        public DateTime CreateDate { get; set; }
    }
  • The user model consist the object of user information.
  • [Table(“Users”)] is belong to System.ComponentModel.DataAnnotations.Schema namespace. Here Users is the table name that we want to create dynamically using EF code first.
  • UserId is the primary key of the table object.
  • CreateDate column is the computed value means it set as default date for this field.
  • User table is use as JWT claim and role based.

After creating the Models class must rebuild the applications. To rebuild the project right click on Project and then click Rebuild.

The user database script look like below.

SET IDENTITY_INSERT [dbo].[Users] ON 

INSERT [dbo].[Users] ([UserId], [FullName], [UserName], [Password], [Email], [CreateDate], [UserRole]) VALUES (1, N'John Doe', N'john', N'john$321', N'john.doe@gmail.com', CAST(N'2020-11-26T00:00:00.0000000' AS DateTime2), N'Admin')
SET IDENTITY_INSERT [dbo].[Users] OFF

Adding the Product API Controller for CRUD REST API

To do database operations to create, update, read and delete over model class we need to create the controller that should do the CRUD operations for us. To create the Controller right click on the Controllers folder and add a new Controller and in the prompt choose as API controller with actions, using Entity framework like below. Here we can use in-built entity framework scaffold technique to create CRUD query for us.

After select the API controller with actions, using Entity framework click the OK button then a new prompt comes again.

  • We select model class is product as we create the model class Product CRUD.
  • DataContext we select as ProductContext, you may change it according to your choice.
  • Then our controller name is ProductsController.

After create the scaffold controller automatically it create the CRUD ( Create, Read, Update, Delete ) operations using Customer Model class and ProductContext class like below.

ProductContext.cs

public class ProductContext : DbContext
    {
        public ProductContext (DbContextOptions<ProductContext> options)
            : base(options)
        {
        }
        public DbSet<ProductCoreService_DOTNET5.Models.Product> Product { get; set; }
        public DbSet<ProductCoreService_DOTNET5.Models.User> User { get; set; }
    }

And it automatically add the DBContext inside the service class of startup.cs like below.

Also the connection string automatically add in appsettings.json file like below. ProductContext is the connection string and value you can modify according to your DB connection.

"ConnectionStrings": {
    "ProductContext": "Server=(localdb)\\mssqllocaldb;Database=ProductContext-2e02db2f-41e9-4ba7-9b78-d0733c05e2b5;Trusted_Connection=True;MultipleActiveResultSets=true"
  }

ProductController.cs

The following REST APIs are created:

  • To list all products: HTTP Get method
  • Get product detail: HTTP Get method
  • Update product detail: HTTP Put method
  • Create product: HTTP Post method
  • Delete product: HTTP Delete method
 [Route("api/[controller]")]
    [ApiController]
    public class ProductsController : ControllerBase
    {
        private readonly ProductContext _context;

        public ProductsController(ProductContext context)
        {
            _context = context;
        }

        // GET: api/Products
        [HttpGet]
        public async Task<ActionResult<IEnumerable<Product>>> GetProduct()
        {
            return await _context.Product.ToListAsync();
        }

        // GET: api/Products/5
        [HttpGet("{id}")]
        public async Task<ActionResult<Product>> GetProduct(int id)
        {
            var product = await _context.Product.FindAsync(id);

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

            return product;
        }

        // PUT: api/Products/5
        // To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754
        [HttpPut("{id}")]
        public async Task<IActionResult> PutProduct(int id, Product product)
        {
            if (id != product.ProductId)
            {
                return BadRequest();
            }

            _context.Entry(product).State = EntityState.Modified;

            try
            {
                await _context.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!ProductExists(id))
                {
                    return NotFound();
                }
                else
                {
                    throw;
                }
            }

            return NoContent();
        }

        // POST: api/Products
        // To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754
        [HttpPost]
        public async Task<ActionResult<Product>> PostProduct(Product product)
        {
            _context.Product.Add(product);
            await _context.SaveChangesAsync();

            return CreatedAtAction("GetProduct", new { id = product.ProductId }, product);
        }

        // DELETE: api/Products/5
        [HttpDelete("{id}")]
        public async Task<IActionResult> DeleteProduct(int id)
        {
            var product = await _context.Product.FindAsync(id);
            if (product == null)
            {
                return NotFound();
            }

            _context.Product.Remove(product);
            await _context.SaveChangesAsync();

            return NoContent();
        }

        private bool ProductExists(int id)
        {
            return _context.Product.Any(e => e.ProductId == id);
        }
    }

Entity Framework Code First Migrations

Code first migrations here help you to create the database for us with following tables Products and Users.

  • Open Package manager console of the project and type the command Add-Migration and hit enter.
  • After executing the command it adds a new file with the name “Initial” prefixed with the date time stamp. It prefixes the date time stamp so that it could track the various migrations added during development and segregate between those. Open the file and we see the class named “Initial” deriving from DbMigration class. This class contains two methods that are overridden from DbMigration class i.e. the base class. The method names are Up() and Down().
  • The final command that creates the database and respective tables out of our context and model. It executes the Initial migration that we added and then runs the seed method from the configuration class. This command is smart enough to detect which migrations to run. For example it will not run previously executed migrations and all the newly added migrations each time will be taken in to account to be executed to update the database. It maintains this track as the database firstly created contains an additional table named __MigrationHistory that keeps track of all the migrations done.
  • The command is Update-Database

After executing the update-database command the database is created like below and now we can test REST CRUD API using Postman tool.

Test REST API CRUD operation using Postman

Before starting to test the API we need to set the route page like below in launchSettings.json

Create product: HTTP Post method

Open the Postman tool and run the application and here we want to create the customer data that means we push the customer information so like below we can push the data.

  • Here http://localhost:49243/api/Customers is the URL to create CRUD operation.
  • Here we want push the information to database so need to choose POST method in Postman.
  • In the Body section append the inputs in json format as formatted above.
  • Click the send button and then the data is pushed to database using post method like below;
  • After click the send button the product data is entered into database using POST method like below.
[HttpPost]
   public async Task<ActionResult<Product>> PostProduct(Product product)
    {
      _context.Product.Add(product);
      await _context.SaveChangesAsync();
      return CreatedAtAction("GetProduct", 
              new { id = product.ProductId }, product);
   }
  • Enter this endpoint into Postman: https://localhost:44305/api/products.
  • Choose POST method and set as header: ‘Content-Type’: ‘application/json’.
  • Under Body Raw, choose type JSON (application/javascript) and paste the product details.

To Get list of all products: HTTP Get method

To fetch all the products that we need to change only method as GET instead of POST.

// GET: api/Products
        [HttpGet]
        public async Task<ActionResult<IEnumerable<Product>>> GetProduct()
        {
            return await _context.Product.ToListAsync();
        }

You can see that doing change is the GET method you can fetch all the product list that inserted in our database.

HERE THE API IS NOT SECURE. That means anybody can access our API without any authentication.

We need to secure the WEB API in different type of authentication methodology. Here we discuss how to secure ASP.NET Core Web API 5.0 using JWT authentication.

Secure ASP.NET Core Web API 5.0 using JWT authentication

Following below steps we can add JWT authentication in ASP .NET Core Web API.

Step-1: Add the below JWT configuration in appsetting.json file

"JwtConfig": {
    "Key": "wRJSMeKKF2QT4fwpMeJf36PO1NiIsInR5cCI6IkNTY3ODkwIG9lIiwiaWF0IjoxN",
    "Issuer": "ProductAuthServer",
    "Audience": "ProductAuthClient",
    "Subject": "ProductAuthAccessToken"
  }
Step-2: Create a controller and check users credentials

Create a controller named as TokenController to perform following operations.

  • Accept username and password as input.
  • Check users credentials with database to ensure users’ identity.
    • If it is valid then access token will be returned.
    • If it is not valid then bad request will be return.
 [Route("api/[controller]")]
    [ApiController]
    public class TokenController : ControllerBase
    {
        public IConfiguration _configuration;
        private readonly ProductContext _context;
        public TokenController(IConfiguration config, ProductContext context)
        {
            _configuration = config;
            _context = context;
        }
        [HttpPost]
        public async Task<IActionResult> Post(User _user)
        {

            if (_user != null && _user.UserName != null && _user.Password != null)
            {
                var user = await GetUser(_user.UserName, _user.Password);

                if (user != null)
                {
                    //create claims details based on the user information
                    var claims = new[] {
                    new Claim(JwtRegisteredClaimNames.Sub, _configuration["JwtConfig:Subject"]),
                    new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
                    new Claim(JwtRegisteredClaimNames.Iat, DateTime.UtcNow.ToString()),
                    new Claim("Id", user.UserId.ToString()),
                    new Claim("FullName", user.FullName),
                    new Claim("UserName", user.UserName),
                    new Claim("Email", user.Email),
                    new Claim("UserRole", user.UserRole)
                   };

                    var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["JwtConfig:Key"]));

                    var signIn = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

                    var token = new JwtSecurityToken(_configuration["JwtConfig:Issuer"], _configuration["JwtConfig:Audience"], claims, expires: DateTime.UtcNow.AddDays(1), signingCredentials: signIn);

                    return Ok(new JwtSecurityTokenHandler().WriteToken(token));
                }
                else
                {
                    return BadRequest("Invalid credentials");
                }
            }
            else
            {
                return BadRequest();
            }
        }

        private async Task<User> GetUser(string username, string password)
        {
            return  _context.User.FirstOrDefault(u => u.UserName == username && u.Password == password);
        }
    }

  • Using JWT claim it creates the token and the below line of code are responsible to create the JWT token.
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["JwtConfig:Key"]));
var signIn = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var token = new JwtSecurityToken(_configuration["JwtConfig:Issuer"], _configuration["JwtConfig:Audience"], claims, expires: DateTime.UtcNow.AddDays(1), signingCredentials: signIn);

Check the JWT token endpoint using Postman

To check the JWT token endpoint in Postman we need to follow the below step.

  • The endpoint is https://localhost:57431/api/token.
  • Choose the POST method and set the header to ‘Content-Type’: ‘application/json’.
  • Choose type JSON in the body section and pass the user information.
  • User credentials is check, and a token will be generated and returned like below.
JWT-token-create

Secure the API endpoint of Product controller

As we have already create the JWT token, then we have secure the endpoint using below steps.

Add the below namespace in startup.cs file.

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
Configure authorization middleware in the startup configureService method.

 services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options =>
            {
                options.RequireHttpsMetadata = false;
                options.SaveToken = true;
                options.TokenValidationParameters = new TokenValidationParameters()
                {
                    ValidateIssuer = true,
                    ValidateAudience = true,
                    ValidAudience = Configuration["JwtConfig:Audience"],
                    ValidIssuer = Configuration["JwtConfig:Issuer"],
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["JwtConfig:Key"]))
                };
            });
  • Here we passed the security key used when creating the token, and we have also enabled validation of Issuer and Audience.
  • Also, we have set SaveToken to true, which stores the bearer token in HTTP Context. So we can access the token in the controller when needed.
Inject the authorization middleware into the Request pipeline in Configure method like below..

JWT authorize
Add the authorization attribute in Product controller, after adding the [Authorize] attribute it secured with the token.

Authorize controller

Test secured REST API using Postman

To fetch the list of product details let’s run the API using postman.

  • Run the API URL http://localhost:49243/api/Products in the postman and see that all list of product are fetch or not.
  • Now you can see that the response status code is 401 Unauthorized. The anonymous access has been blocked and the APIs have been secured. Let’s understand how to access this secure API controller.

How to access secured API passing JWT token

We have already create the JWT token, so we need to pass the authentication token inside in authorization header like below,

Run the Token controller to generate the JWT token. (http://localhost:57431/api/token)

Prepend the text Bearer with this token, the token is as follows.

Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJQcm9kdWN0QXV0aEFjY2Vzc1Rva2VuIiwianRpIjoiNTQ4ODlkMzgtNzM4MS00YjE1LTkyM2UtZjY3ZTI1YWQwOTg0IiwiaWF0IjoiMTIvOS8yMDIwIDU6NDk6MDUgUE0iLCJJZCI6IjEiLCJGdWxsTmFtZSI6IkpvaG4gRG9lIiwiVXNlck5hbWUiOiJqb2huIiwiRW1haWwiOiJqb2huLmRvZUBnbWFpbC5jb20iLCJVc2VyUm9sZSI6IkFkbWluIiwiZXhwIjoxNjA3NjIyNTQ1LCJpc3MiOiJQcm9kdWN0QXV0aFNlcnZlciIsImF1ZCI6IlByb2R1Y3RBdXRoQ2xpZW50In0.-v90K5lXun9bmxkeitCd1syoz8Sv3Ebcr5fF2ZbYtp4

Under the Authorization header pass the token in the headers part, and then click Send.

  • When we pass the authorization header to the API, authentication middleware parses and validates the token. If it is found valid, it will set Identity.IsAuthenticated to true.
  • The Authorize attribute added in the controller will check whether the request is authenticated. If it is true, the API can be accessed.
  • If Identity.IsAuthenticated returns false, a 401 unauthorized error will be returned.

Boom ! Now you can see the JWT token is working perfectly. If the token is valid then it return appropriate result else return 401 unauthorized.

Find the Source Code on Github

Summary

This article explain how to create a REST API using ASP.NET Core 5.0 and Entity Framework Core to perform basic CRUD operations, create a JWT token, and secure the API.

That’s a wrap for this article. I hope that it cleared about Build CRUD REST APIs with ASP.NET Core 5.0 with EF Core 5.0. Please write to us if have any.

Have you enjoyed this post and found it useful? If so, please consider supporting me:

Buy me a coffeeBuy me a coffee


Related Post

In-Memory Caching in ASP.NET Core-Basic guide of Caching
in memory caching

This article explain about In-Memory Caching in ASP.NET Core, We discussed here Caching, the Basics, In-Memory Caching, Implementing In-Memory Caching Read more

CQRS pattern with MediatR in ASP.NET Core 5.0
CQRS pattern with MediatR in ASP.NET Core 5.0

This article explain CQRS design pattern with MediatR in ASP.Net Core 5.0. CQRS is a design pattern that separated the Read more

ASP.NET Core Web API with MongoDB CRUD- Beginner’s Guide
ASP.NET CORE WEB API 5.0 MONGODB CRUD

This article explain CRUD operation using MongoDB in ASP.NET Core Web API. We discuss here basics of MongoDB and how Read more

How to send Email in ASP.NET Core-Beginner’s Guide
How to send Email in ASP.NET Core

This article explain how to send Email in ASP.NET Core using Mailkit. It is open-source cross-platform library that can be Read more

Pin It on Pinterest