<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://girishgodage.in/feed.xml" rel="self" type="application/atom+xml" /><link href="https://girishgodage.in/" rel="alternate" type="text/html" /><updated>2024-09-26T10:15:08+00:00</updated><id>https://girishgodage.in/feed.xml</id><title type="html">Girish Godage</title><subtitle>I am a passionate Leader, who has a good command in technology &amp; Mangement. Also, I am a creative designer and an innovatie techie.</subtitle><author><name>Girish Godage</name></author><entry><title type="html">UPLOADING DOWNLOADING AND DELETING FILES IN AWS S3 CLOUD STORAGE USING ASP.NET CORE</title><link href="https://girishgodage.in/blog/uploading-downloading-and-deleting-files-in-aws-s3-cloud-storage-using-asp-net-core" rel="alternate" type="text/html" title="UPLOADING DOWNLOADING AND DELETING FILES IN AWS S3 CLOUD STORAGE USING ASP.NET CORE" /><published>2021-03-10T05:54:00+00:00</published><updated>2021-03-10T05:54:00+00:00</updated><id>https://girishgodage.in/blog/documentupload-in-S3-using-aspnetcore</id><content type="html" xml:base="https://girishgodage.in/blog/uploading-downloading-and-deleting-files-in-aws-s3-cloud-storage-using-asp-net-core"><![CDATA[<h2 id="uploading-downloading-and-deleting-files-in-aws-s3-cloud-storage-using-aspnet-core">UPLOADING DOWNLOADING AND DELETING FILES IN AWS S3 CLOUD STORAGE USING ASP.NET CORE</h2>

<p>This article will learn how to upload , download and delete files from amazon AWS S3 Cloud Storage using ASP.NET CORE.</p>

<h2 id="what-is-amazon-s3">What is Amazon S3?</h2>

<p>Amazon S3 has a simple web services interface that you can use to store and retrieve any amount of data, at any time, from anywhere on the web.</p>

<p>https://docs.aws.amazon.com/AmazonS3/latest/userguide/Welcome.html</p>

<h2 id="what-youll-be-building">What you’ll be building</h2>

<p>In this article, you’ll learn the following</p>

<ul>
  <li>Creating application ASP.NET Core Application</li>
  <li>Installing packages from NuGet</li>
  <li>Creating a Bucket</li>
  <li>View after creating a bucket.</li>
  <li>Creating a User</li>
  <li>Adding a User to Group and assigning policy</li>
  <li>Created Table for Storing Documents</li>
  <li>Added Entity and DbContext class along with interface and Concrete for Storing and Reading the documents</li>
  <li>AppSettings for Storing AccessKey and SecretKey  configuring database connection string</li>
  <li>Creating Controller</li>
  <li>Upload File</li>
  <li>AllFiles</li>
  <li>Download file</li>
  <li>Delete file</li>
</ul>

<h3 id="creating-application-aspnet-core-application">Creating application ASP.NET Core Application</h3>

<p><img src="/img/aspdotnetcore/1/01.png" alt="image" /></p>

<p>Next, we are going to set Project Name <strong>“WebStorageDemo”</strong> and location.</p>

<p>We will choose .Net Core framework and ASP.NET Core Version 5.0 as the framework for application and we are not going to enable docker settings for this project.</p>

<p><img src="/img/aspdotnetcore/1/02.png" alt="image" /></p>

<p>Now finally click on create button to create a project.</p>

<p><strong>Project structure</strong></p>

<p>The project structure generated according to the configuration.</p>

<p><img src="/img/aspdotnetcore/1/03.png" alt="image" /></p>

<p>After creating project next, we are going to install below package from NuGet Packages.</p>

<h3 id="installing-a-package-from-nuget">Installing a package from NuGet</h3>

<ol>
  <li>
    <p>WindowsAzure.Storage</p>

    <p><img src="/img/aspdotnetcore/1/04.png" alt="image" /></p>
  </li>
  <li>
    <p>Microsoft.EntityFrameworkCore</p>

    <p><img src="/img/aspdotnetcore/1/05.png" alt="image" /></p>
  </li>
  <li>
    <p>Microsoft.EntityFrameworkCore.SqlServer</p>

    <p><img src="/img/aspdotnetcore/1/06.png" alt="image" /></p>
  </li>
</ol>

<p>After installing packages next, we will create a bucket for that we must have an AWS account.</p>

<p>If you do not have an account, then create one account for free. https://aws.amazon.com/</p>

<p>I have already created an AWS account and logged in to the portal, for creating a bucket.</p>

<h3 id="creating-a-bucket">Creating a Bucket</h3>

<p>The bucket is a virtual container where we are going to store all objects.</p>

<p>For using Amazon S3 service, we must search S3 service in search.</p>

<p><img src="/img/aspdotnetcore/1/07.png" alt="image" /></p>

<p>After selecting S3 service, it redirects to buckets page.</p>

<p><img src="/img/aspdotnetcore/1/08.png" alt="image" /></p>

<p>Here for creating a bucket, we need to click on Create bucket button.</p>

<p>For creating a bucket, we need to enter a unique bucket name and select region where you want this bucket to be made.</p>

<p><img src="/img/aspdotnetcore/1/09.png" alt="image" /></p>

<p>Here we are going to enter the name of bucket <strong>(myawscorebucket)</strong> and then select region as “Asia Pacific (Mumbai)” after selecting just scroll your page then you will find <strong>“Block Public Access settings for bucket”</strong> here for the demo I am going to uncheck all checkboxes you must uncheck it according to your need.</p>

<p><img src="/img/aspdotnetcore/1/10.png" alt="image" /></p>

<p>Just scroll your page below you will find create bucket button just click on it to create a bucket.</p>

<p><img src="/img/aspdotnetcore/1/11.png" alt="image" /></p>

<h3 id="view-after-creating-a-bucket">View after creating a bucket</h3>

<p><img src="/img/aspdotnetcore/1/12.png" alt="image" /></p>

<p>After creating a bucket next, we are going to create a user for we need to search IAM <strong>(Identity and Access Management).</strong></p>

<p><strong>Adding a User</strong></p>

<p><img src="/img/aspdotnetcore/1/13.png" alt="image" /></p>

<p>After selecting IAM, you will see below screen.</p>

<p><img src="/img/aspdotnetcore/1/14.png" alt="image" /></p>

<p>After clicking on Add user, we will add a user name and select Access type as shown below.</p>

<p><img src="/img/aspdotnetcore/1/15.png" alt="image" /></p>

<p>After filling in all details, click on the next permission button.</p>

<h3 id="adding-a-user-to-group-and-assigning-policy">Adding a User to Group and assigning policy</h3>

<p><img src="/img/aspdotnetcore/1/16.png" alt="image" /></p>

<p>We will create a group with the name “AWSS3FullAccess” and assign policy (AmazonS3FullAccess) to access Amazon S3.</p>

<p><img src="/img/aspdotnetcore/1/17.png" alt="image" /></p>

<p>Just click on Create group button for creating a group. Next step will be making tags I will skip it, and the final screen will be Review as shown below.</p>

<p><img src="/img/aspdotnetcore/1/18.png" alt="image" /></p>

<p>The review page will show all details that you have configured just click on create a user it will create user successfully as shown below.</p>

<p><img src="/img/aspdotnetcore/1/19.png" alt="image" /></p>

<p>Now you have <strong>Access key ID</strong> and <strong>Secret access key</strong> for accessing S3 Services. Next, we have created a table in the database to store document details.</p>

<h3 id="created-table-for-storing-documents">Created Table for Storing Documents</h3>

<p>Creating a table with name <strong>DocumentStore</strong> for storing document details.</p>

<p><img src="/img/aspdotnetcore/1/20.png" alt="image" /></p>

<p>Added Entity and DbContext class along with interface and Concrete for Storing and Reading the document.</p>

<p><img src="/img/aspdotnetcore/1/21.png" alt="image" /></p>

<p>In this part first, we have added the DocumentStore Entity.</p>

<pre><code class="language-code">
  using System;
  using System.ComponentModel.DataAnnotations;
  using System.ComponentModel.DataAnnotations.Schema;

  namespace WebStorageDemo.Models
  {
      [Table("DocumentStore")]
      public class DocumentStore
      {
          [Key]
          public int DocumentId { get; set; }
          public string DocumentName { get; set; }
          public string DocumentType { get; set; }
          public DateTime CreatedOn { get; set; }
      }
  }

</code></pre>

<p>Next, we have added DbContext with name BlobDbContext.</p>

<pre><code class="language-code">  using Microsoft.EntityFrameworkCore;
  using WebStorageDemo.Models;

  namespace WebStorageDemo.Repository
  {
      public class BlobDbContext : DbContext
      {
          public BlobDbContext(DbContextOptions&lt;BlobDbContext&gt; options) : base(options)
          {
          }
          public DbSet&lt;DocumentStore&gt; DocumentStore { get; set; }
      }
  }
</code></pre>

<p>After adding BlobDbContext next, we are going to add Interface and Concrete in the Repository folder.</p>

<pre><code class="language-code">
  using System.Collections.Generic;
  using WebStorageDemo.Models;

  namespace WebStorageDemo.Repository
  {
      public interface IDocumentData
      {
          void Add(DocumentStore documentStore);
          List&lt;DocumentStore&gt; GetDocumentStoresList();
          void Delete(DocumentStore documentStore);
          DocumentStore GetDocumentbyDocumentId(int documentId);
      }
  }
</code></pre>

<p>AppSettings for Storing AccessKey and SecretKey and configuring database connection string</p>

<blockquote>
  <p>It is not recommended to store the keys in the appsettings.json file you can use the best methods available for the demo I am storing keys in the appsettings.json file.</p>
</blockquote>

<p><img src="/img/aspdotnetcore/1/22.png" alt="image" /></p>

<p>After setting keys in the appsettings.json file next, we will configure entity framework core, appsettings and registering IDocumentData interface.</p>

<pre><code class="language-code">
public void ConfigureServices(IServiceCollection services)
{
    services.AddScoped&lt;IDocumentData, DocumentData&gt;();
    var connection = Configuration.GetConnectionString("DatabaseConnection");
    services.AddDbContext&lt;BlobDbContext&gt;(options =&gt; options.UseSqlServer(connection));
    services.Configure&lt;AppSettings&gt;(Configuration.GetSection("AwsSettings"));
    services.AddControllersWithViews();
}

</code></pre>

<p>Everything is configured now let’s Create Controller for Uploading, Downloading and Deleting files.</p>

<h3 id="creating-controller">Creating Controller</h3>

<p>We will create Controller With name <strong>DemoController</strong> with different action methods such as <strong>UploadFile, DeleteFile, DownloadFile and AllFiles</strong>.</p>

<p><strong>Upload File</strong></p>

<p>We will access 2 things in Controller AppSettings, IDocumentData from appsettings we will get bucket name, Access key and Secret key, we will pass Access key and Secret key to BasicAWSCredentials method and then set RegionEndpoint.</p>

<p>After that, we will get uploaded files details from <strong>IFromFile</strong> interface that we will assign to <strong>TransferUtilityUploadRequest</strong> class of AWS and then finally call <strong>TransferUtility</strong> class and access UploadAsync method to upload file meanwhile we are going to store all document details to the database.</p>

<pre><code class="language-code">        [HttpGet]
        public IActionResult UploadFile()
        {
            return View();
        }

        [HttpPost]
        public async Task&lt;IActionResult&gt; UploadFile(IFormFile file)
        {
            try
            {

                var bucketName = !string.IsNullOrWhiteSpace(_appSettings.FolderName)
                    ? _appSettings.BucketName + @"/" + _appSettings.FolderName
                    : _appSettings.BucketName;

                var credentials = new BasicAWSCredentials(_appSettings.AccessKey, _appSettings.SecretKey);
                var config = new AmazonS3Config
                {
                    RegionEndpoint = Amazon.RegionEndpoint.APSouth1
                };


                using var client = new AmazonS3Client(credentials, config);
                await using var newMemoryStream = new MemoryStream();
                await file.CopyToAsync(newMemoryStream);

                var fileExtension = Path.GetExtension(file.FileName);
                var documentName = $"{GenerateId()}{fileExtension}";

                // URL for Accessing Document for Demo
                var result = $"https://{bucketName}.s3.amazonaws.com/{documentName}";

                var uploadRequest = new TransferUtilityUploadRequest
                {
                    InputStream = newMemoryStream,
                    Key = documentName,
                    BucketName = bucketName,
                    CannedACL = S3CannedACL.PublicRead
                };

                var fileTransferUtility = new TransferUtility(client);
                await fileTransferUtility.UploadAsync(uploadRequest);

                DocumentStore documentStore = new DocumentStore()
                {
                    CreatedOn = DateTime.Now,
                    DocumentId = 0,
                    DocumentName = documentName,
                    DocumentType = file.ContentType
                };

                _documentdata.Add(documentStore);

            }
            catch (AmazonS3Exception amazonS3Exception)
            {
                if (amazonS3Exception.ErrorCode != null
                    &amp;&amp; (amazonS3Exception.ErrorCode.Equals("InvalidAccessKeyId") || amazonS3Exception.ErrorCode.Equals("InvalidSecurity")))
                {
                    throw new Exception("Check the provided AWS Credentials.");
                }
                else
                {
                    throw new Exception("Error occurred: " + amazonS3Exception.Message);
                }
            }
            return RedirectToAction("AllFiles");
        }

</code></pre>

<h3 id="output">Output</h3>

<p>We are going to access the Demo/UploadFile path for uploading the file.</p>

<p><img src="/img/aspdotnetcore/1/23.png" alt="image" /></p>

<p>After uploading the file, we can see in AWS S3 objects section as shown below.</p>

<p><img src="/img/aspdotnetcore/1/24.png" alt="image" /></p>

<p>While uploading data, we are storing file details in the database.</p>

<p><img src="/img/aspdotnetcore/1/25.png" alt="image" /></p>

<h3 id="all-files">All Files</h3>

<p>In this part, we are going to show all files which are stored in the database along with download and delete feature.</p>

<pre><code class="language-code">
  public IActionResult AllFiles()
    {
      return View(_documentdata.GetDocumentStoresList());
    }
</code></pre>

<p><img src="/img/aspdotnetcore/1/26.png" alt="image" /></p>

<h3 id="all-files-view">All Files View</h3>

<pre><code class="language-code">
@model List&lt;DocumentStore&gt;

&lt;table class="table table-striped"&gt;
    &lt;thead&gt;
        &lt;tr&gt;
            &lt;th&gt;DocumentId&lt;/th&gt;
            &lt;th&gt;DocumentName&lt;/th&gt;
            &lt;th&gt;CreatedOn&lt;/th&gt;
            &lt;th&gt;Download&lt;/th&gt;
            &lt;th&gt;Delete&lt;/th&gt;
        &lt;/tr&gt;
    &lt;/thead&gt;
    &lt;tbody&gt;

        @foreach (var data in Model)
        {
        &lt;tr&gt;
            &lt;td&gt;@data.DocumentId&lt;/td&gt;
            &lt;td&gt;@data.DocumentName&lt;/td&gt;
            &lt;td&gt;@data.CreatedOn&lt;/td&gt;
            &lt;td&gt;
                &lt;a class="btn btn-success" href="/Demo/DownloadFile/@data.DocumentId"&gt;Download&lt;/a&gt;
            &lt;/td&gt;
            &lt;td&gt;
                &lt;a class="btn btn-danger" href="/Demo/DeleteFile/@data.DocumentId"&gt;Delete&lt;/a&gt;
            &lt;/td&gt;
           
        &lt;/tr&gt;
        }
    &lt;/tbody&gt;
&lt;/table&gt;

</code></pre>

<h3 id="download-file">Download file</h3>

<p>We have created the DownloadFile action method for downloading, which takes document id as an input parameter and then gets document details. From this document details, we will take document name and pass it to GetObjectAsync method, which will get an object from S3 Bucket which contains ResponseStream and objectResponse.Headers.ContentType.</p>

<pre><code class="language-code">public async Task&lt;IActionResult&gt; DownloadFile(int id)
        {
            try
            {
                var getdocument = _documentdata.GetDocumentbyDocumentId(id);
                var credentials = new BasicAWSCredentials(_appSettings.AccessKey, _appSettings.SecretKey);
                var config = new AmazonS3Config
                {
                    RegionEndpoint = Amazon.RegionEndpoint.APSouth1
                };
                using var client = new AmazonS3Client(credentials, config);
                var fileTransferUtility = new TransferUtility(client);

                var objectResponse = await fileTransferUtility.S3Client.GetObjectAsync(new GetObjectRequest()
                {
                    BucketName = _appSettings.BucketName,
                    Key = getdocument.DocumentName
                });

                if (objectResponse.ResponseStream == null)
                {
                    return NotFound();
                }
                return File(objectResponse.ResponseStream, objectResponse.Headers.ContentType, getdocument.DocumentName);
            }
            catch (AmazonS3Exception amazonS3Exception)
            {
                if (amazonS3Exception.ErrorCode != null
                    &amp;&amp; (amazonS3Exception.ErrorCode.Equals("InvalidAccessKeyId") || amazonS3Exception.ErrorCode.Equals("InvalidSecurity")))
                {
                    throw new Exception("Check the provided AWS Credentials.");
                }
                else
                {
                    throw new Exception("Error occurred: " + amazonS3Exception.Message);
                }
            }

        }
</code></pre>

<p><strong>Output</strong></p>

<p><img src="/img/aspdotnetcore/1/27.png" alt="image" /></p>

<h3 id="delete-file">Delete file</h3>

<p>For Deleting file, we have created a DeleteFile action method that takes document id as an input parameter and then documents details. From this document details, we will take document name and pass it to DeleteObjectAsync method which will delete an object from S3 Bucket while we are going call delete method from DocumentData class delete the file from the database.</p>

<pre><code class="language-code">public async Task&lt;IActionResult&gt; DeleteFile(int id)
        {
            try
            {
                var getdocument = _documentdata.GetDocumentbyDocumentId(id);
                _documentdata.Delete(getdocument);

                var credentials = new BasicAWSCredentials(_appSettings.AccessKey, _appSettings.SecretKey);
                var config = new AmazonS3Config
                {
                    RegionEndpoint = Amazon.RegionEndpoint.APSouth1
                };
                using var client = new AmazonS3Client(credentials, config);
                var fileTransferUtility = new TransferUtility(client);
                await fileTransferUtility.S3Client.DeleteObjectAsync(new DeleteObjectRequest()
                {
                    BucketName = _appSettings.BucketName,
                    Key = getdocument.DocumentName
                });

            }
            catch (AmazonS3Exception amazonS3Exception)
            {
                if (amazonS3Exception.ErrorCode != null
                    &amp;&amp; (amazonS3Exception.ErrorCode.Equals("InvalidAccessKeyId") || amazonS3Exception.ErrorCode.Equals("InvalidSecurity")))
                {
                    throw new Exception("Check the provided AWS Credentials.");
                }
                else
                {
                    throw new Exception("Error occurred: " + amazonS3Exception.Message);
                }
            }
            return RedirectToAction("AllFiles");
        }

</code></pre>

<p><strong>Before delete</strong></p>

<p><img src="/img/aspdotnetcore/1/28.png" alt="image" /></p>

<p><strong>After delete</strong></p>

<p><img src="/img/aspdotnetcore/1/29.png" alt="image" /></p>

<p><strong>Output</strong></p>

<p><img src="/img/aspdotnetcore/1/30.png" alt="image" /></p>

<h2 id="summary">Summary</h2>

<p>In this article, we have learned how to upload , download and delete files from amazon AWS S3 Cloud Storage using ASP.NET CORE in simple steps hope you have like it please share it let others learn from it.</p>]]></content><author><name>Girish Godage</name></author><category term="DotnetCore" /><category term="learning" /><summary type="html"><![CDATA[UPLOADING DOWNLOADING AND DELETING FILES IN AWS S3 CLOUD STORAGE USING ASP.NET CORE]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://girishgodage.in/img/aspnetcore.png" /><media:content medium="image" url="https://girishgodage.in/img/aspnetcore.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">HOW TO IMPLEMENT GLOBALIZATION AND LOCALIZATION IN ASP.NET CORE</title><link href="https://girishgodage.in/blog/how-to-implement-globalization-and-localization-in-asp-net-core" rel="alternate" type="text/html" title="HOW TO IMPLEMENT GLOBALIZATION AND LOCALIZATION IN ASP.NET CORE" /><published>2021-02-15T05:54:00+00:00</published><updated>2021-02-15T05:54:00+00:00</updated><id>https://girishgodage.in/blog/how-to-implement-globalization-and-localization-in-asp-net-core</id><content type="html" xml:base="https://girishgodage.in/blog/how-to-implement-globalization-and-localization-in-asp-net-core"><![CDATA[<h2 id="how-to-implement-globalization-and-localization-in-aspnet-core">HOW TO IMPLEMENT GLOBALIZATION AND LOCALIZATION IN ASP.NET CORE</h2>

<p>In this article, we are going to learn how to implement Globalization and Localization in simple steps.</p>

<p><a href="https://github.com/girishgodage/WebDemo">Github link for Source</a></p>

<p><img src="/img/aspdotnetcore/3/08.png" alt="image" /></p>

<h3 id="what-is-globalization-and-localization">What is Globalization and Localization?</h3>

<p>Globalization is the process of designing the application in such a way that it can be used by users from across the globe (multiple cultures).</p>

<p>Localization, on the other hand, is the process of customization to make our application behave depending on the current Culture and locale. These two things go together.</p>

<blockquote>
  <p>I am writing this article because I was trying to Implement Globalization and Localization in one of my projects which took a lot of time to create a working demo reading Microsoft document. Trying to write a simple version which is easy to implement in your projects.</p>
</blockquote>

<ul>
  <li>DataAnnotations localization</li>
  <li>View localization and Accessing localization string in Controller</li>
</ul>

<h3 id="table-of-contents">Table of Contents</h3>

<ul>
  <li>Getting Started with Globalization and Localization in ASP.NET Core</li>
  <li>Project structure</li>
  <li>Adding Model and Setting Display Properties</li>
  <li>Adding Folder to Keep Resource Files</li>
  <li>Adding Resource Files in Folder</li>
  <li>Adding Dummy Class</li>
  <li>Configure Localization in ConfigureServices Method</li>
  <li>Configure Localization middleware in Configure Method</li>
  <li>Adding Culture Controller</li>
  <li>Adding Partial View (“_SetLanguagePartial.cshtml”)</li>
  <li>Calling SetLanguagePartial View in Layout</li>
  <li>Adding Customer Controller</li>
  <li>Adding Customer View</li>
  <li>Output</li>
  <li>Accessing Resources in Controller and View</li>
  <li>Register service in ConfigureServices Method in Startup class.</li>
  <li>Output</li>
  <li>Accessing LocalizationService on View</li>
  <li>Output</li>
  <li>View localization</li>
  <li>Values to Access on View Using ViewLocalizer</li>
  <li>Output</li>
</ul>

<p>We are going to create a new application with Name WebDemo for demo as shown below.</p>

<p><img src="/img/aspdotnetcore/3/01.png" alt="image" /></p>

<p>Next, we are going to set Project Name “WebDemo” and location. In last part, we are going to choose .Net Core framework and ASP.NET Core Version 5.0 as the framework for application and few advance settings for such as configuring https and enabling docker we are not going to enable docker settings for this project.</p>

<p><img src="/img/aspdotnetcore/3/02.png" alt="image" /></p>

<p>Now finally click on create button to create a project.</p>

<h3 id="project-structure">Project structure</h3>

<p>The project structure generated according to the configuration.</p>

<p><img src="/img/aspdotnetcore/3/03.png" alt="image" /></p>

<p>After creating project next, we are going create Model and Adding properties which we are going to localize.</p>

<h3 id="adding-model-and-setting-display-properties">Adding Model and Setting Display Properties</h3>

<p>We are going to adding <strong>CustomerViewModel</strong> in Model Folder. If you want to keep ViewModel in separate Class Library, you can do it.</p>

<p>Next, we have created 3 properties and also set its Display properties. This Display properties Name Must be same as Your Resource File Name. Which we are going to add in the next step.</p>

<pre><code class="language-code">
using System.ComponentModel.DataAnnotations;
namespace WebDemo.Models
{
    public class CustomerViewModel
    {
        [Display(Name = "FullName")]
        public string FullName { get; set; }

        [Display(Name = "City")]
        public string City { get; set; }

        [Display(Name = "MobileNo")]
        public string MobileNo { get; set; }
    }
}

</code></pre>

<h3 id="adding-folder-to-keep-resource-files">Adding Folder to Keep Resource Files</h3>

<p>We are going to add a folder with Name “<strong>Resource</strong>” to stored resources in it.</p>

<p><img src="/img/aspdotnetcore/3/04.png" alt="image" /></p>

<h3 id="adding-resource-files-in-folder">Adding Resource Files in Folder</h3>

<p>Here we are going to add a resource file in the resources folder. We are going to create 5 resources file with for storing 5 different culture string in it.</p>

<blockquote>
  <p>en (English)</p>

  <p>hi (Hindi)</p>

  <p>ar (Arabic)</p>

  <p>de (German)</p>

  <p>zh (Chinese)</p>
</blockquote>

<p>For adding Resource file just right click on Resource folder select Add -&gt; New Item after select Add New Item Dialog will be displayed.</p>

<p>In Search type “Resource” to search resource file.</p>

<p><img src="/img/aspdotnetcore/3/05.png" alt="image" /></p>

<p>We are going to Name files as “ApplicationResource”, and each file name will have culture name in it.</p>

<p>Example</p>

<blockquote>
  <p>ApplicationResource.en.resx</p>

  <p>ApplicationResource.hi.resx</p>

  <p>ApplicationResource.ar.resx</p>

  <p>ApplicationResource.de.resx</p>

  <p>ApplicationResource.zh.resx</p>
</blockquote>

<h3 id="project-view-after-adding-resources-files">Project View after adding Resources Files</h3>

<p><img src="/img/aspdotnetcore/3/06.png" alt="image" /></p>

<p>Each file we are going to add Name (Key) and Value. This is English file here we are going to keep Value in English.</p>

<p><img src="/img/aspdotnetcore/3/07.png" alt="image" /></p>

<p>Next, we are going to do the same add Name and Different Values according to culture files.</p>

<p>Below you see different resources file has the same name and different Values.</p>

<p><img src="/img/aspdotnetcore/3/08.png" alt="image" /></p>

<h3 id="adding-dummy-class">Adding Dummy Class</h3>

<p>Dummy class to group resources files. We are going to add Class with the name “ApplicationResource”.</p>

<pre><code class="language-code">namespace WebDemo.Resources
{
    public class ApplicationResource
    {
    }
}

</code></pre>

<p><img src="/img/aspdotnetcore/3/09.png" alt="image" /></p>

<h3 id="configure-localization-in-configureservices-method">Configure Localization in ConfigureServices Method</h3>

<p>We are going to Configure localization “Startup.ConfigureServices” Method.</p>

<p>Adds services required for application localization. In ResourcesPath option we are going set resource folder named “Resources”.</p>

<pre><code class="language-code">services.AddLocalization(options =&gt; options.ResourcesPath = "Resources");
</code></pre>

<pre><code class="language-code">
services.AddMvc()
 .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
 .AddDataAnnotationsLocalization(options =&gt;
 {
     options.DataAnnotationLocalizerProvider = (type, factory) =&gt;
     {
         var assemblyName = new AssemblyName(typeof(ApplicationResource).GetTypeInfo().Assembly.FullName);
         return factory.Create("ApplicationResource", assemblyName.Name);
     };
 });

</code></pre>

<p>Next, we are going configure RequestLocalizationOptions for application.</p>

<p>In this part, we are going add Cultures which we are going to use in application and set default culture.</p>

<pre><code class="language-code">
services.Configure&lt;RequestLocalizationOptions&gt;(options =&gt;
{
    var supportedCultures = new[]
    {
        new CultureInfo("en"),
        new CultureInfo("ar"),
        new CultureInfo("de"),
        new CultureInfo("hi"),
        new CultureInfo("zh"),
    };

    // State what the default culture for your application is. This will be used if no specific culture
    // can be determined for a given request.
    options.DefaultRequestCulture = new RequestCulture("en");

    // You must explicitly state which cultures your application supports.
    // These are the cultures the app supports for formatting numbers, dates, etc.
    options.SupportedCultures = supportedCultures;

    // These are the cultures the app supports for UI strings, i.e. we have localized resources for.
    options.SupportedUICultures = supportedCultures;
});

</code></pre>

<h3 id="configure-localization-middleware-in-configure-method">Configure Localization middleware in Configure Method</h3>

<p>Adding <strong>UseRequestLocalization</strong> middleware to the HTTP pipeline (Configure Method).
It should be added below UseRouting Middleware.</p>

<pre><code class="language-code">app.UseRouting();

var requestlocalizationOptions = app.ApplicationServices.GetService&lt;IOptions&lt;RequestLocalizationOptions&gt;&gt;();
app.UseRequestLocalization(requestlocalizationOptions.Value);

</code></pre>

<pre><code class="language-code">
public void ConfigureServices(IServiceCollection services)
{
    services.AddLocalization(options =&gt; options.ResourcesPath = "Resources");
    
    services.AddMvc()
        .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
        .AddDataAnnotationsLocalization(options =&gt;
        {
            options.DataAnnotationLocalizerProvider = (type, factory) =&gt;
            {
                var assemblyName = new AssemblyName(typeof(ApplicationResource).GetTypeInfo().Assembly.FullName);
                return factory.Create("ApplicationResource", assemblyName.Name);
            };
        });

    services.Configure&lt;RequestLocalizationOptions&gt;(options =&gt;
    {
        var supportedCultures = new[]
        {
            new CultureInfo("en"),
            new CultureInfo("ar"),
            new CultureInfo("de"),
            new CultureInfo("hi"),
            new CultureInfo("zh"),
        };

        // State what the default culture for your application is. This will be used if no specific culture
        // can be determined for a given request.
        options.DefaultRequestCulture = new RequestCulture("en");

        // You must explicitly state which cultures your application supports.
        // These are the cultures the app supports for formatting numbers, dates, etc.
        options.SupportedCultures = supportedCultures;

        // These are the cultures the app supports for UI strings, i.e. we have localized resources for.
        options.SupportedUICultures = supportedCultures;
    });

    services.AddControllersWithViews();
}
</code></pre>

<p>After configuring Middleware Next, let’s Add Controller.</p>

<h3 id="adding-culture-controller">Adding Culture Controller</h3>

<p>In this part, we are going to add Controller which we are going to call from UI to set Culture and store in Cookie such that it is available for the entire application.</p>

<pre><code class="language-code">
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Localization;
using Microsoft.AspNetCore.Mvc;
using System;

namespace WebDemo.Controllers
{
    public class CultureController : Controller
    {
        [HttpPost]
        public IActionResult SetLanguage(string culture, string returnUrl)
        {
            Response.Cookies.Append(
                CookieRequestCultureProvider.DefaultCookieName,
                CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture)),
                new CookieOptions { Expires = DateTimeOffset.UtcNow.AddYears(1) }
            );

            return LocalRedirect(returnUrl);
        }
    }
}

</code></pre>

<h3 id="adding-partial-view--adding-partial-view-_setlanguagepartialcshtml">Adding Partial View  Adding Partial View (“_SetLanguagePartial.cshtml”)</h3>

<p>In this part, we are going to add Partial View (“_SetLanguagePartial.cshtml”) in Views –&gt; Shared folder.</p>

<p>Partial View will have a Dropdown list with culture names for selection of Culture. After selecting Culture,</p>

<p>we are going to POST Values to Culture Controller Set Language Action Method and set culture value to Cookie and reload the page.</p>

<p><img src="/img/aspdotnetcore/3/10.png" alt="image" /></p>

<pre><code class="language-code">@using Microsoft.AspNetCore.Builder
@using Microsoft.AspNetCore.Localization
@using Microsoft.AspNetCore.Mvc.Localization
@using Microsoft.Extensions.Options

@inject IViewLocalizer Localizer
@inject IOptions&lt;RequestLocalizationOptions&gt; LocOptions
@{
    var requestCulture = Context.Features.Get&lt;IRequestCultureFeature&gt;();
    var cultureItems = LocOptions.Value.SupportedUICultures
        .Select(c =&gt; new SelectListItem { Value = c.Name, Text = c.DisplayName })
        .ToList();
}

&lt;div&gt;
    &lt;form asp-controller="Culture"
          asp-action="SetLanguage"
          asp-route-returnUrl="@Context.Request.Path"
          method="post"&gt;
        Language :-
        &lt;select name="culture"
                onchange="this.form.submit();"
                asp-for="@requestCulture.RequestCulture.UICulture.Name"
                asp-items="cultureItems"&gt;
        &lt;/select&gt;
    &lt;/form&gt;
&lt;/div&gt;

</code></pre>

<h3 id="calling-setlanguagepartial-view-in-layout">Calling SetLanguagePartial View in Layout</h3>

<p>In this part, we are going to call _SetLanguagePartial view on Layout.</p>

<pre><code class="language-code">
 @await Html.PartialAsync("_SetLanguagePartial")

</code></pre>

<pre><code class="language-code">
 &lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
&lt;head&gt;
    &lt;meta charset="utf-8" /&gt;
    &lt;meta name="viewport" content="width=device-width, initial-scale=1.0" /&gt;
    &lt;title&gt;@ViewData["Title"] - WebDemo&lt;/title&gt;
    &lt;link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" /&gt;
    &lt;link rel="stylesheet" href="~/css/site.css" /&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;header&gt;
        &lt;nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3"&gt;
            &lt;div class="container"&gt;
                &lt;a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index"&gt;WebDemo&lt;/a&gt;
                &lt;button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                        aria-expanded="false" aria-label="Toggle navigation"&gt;
                    &lt;span class="navbar-toggler-icon"&gt;&lt;/span&gt;
                &lt;/button&gt;
                &lt;div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse"&gt;
                    &lt;ul class="navbar-nav flex-grow-1"&gt;
                        &lt;li&gt;
                            @await Html.PartialAsync("_SetLanguagePartial")
                        &lt;/li&gt;
                    &lt;/ul&gt;
                &lt;/div&gt;
            &lt;/div&gt;
        &lt;/nav&gt;
    &lt;/header&gt;
    &lt;div class="container"&gt;
        &lt;main role="main" class="pb-3"&gt;
            @RenderBody()
        &lt;/main&gt;
    &lt;/div&gt;

    &lt;footer class="border-top footer text-muted"&gt;
        &lt;div class="container"&gt;
            &amp;copy; 2020 - WebDemo - &lt;a asp-area="" asp-controller="Home" asp-action="Privacy"&gt;Privacy&lt;/a&gt;
        &lt;/div&gt;
    &lt;/footer&gt;
    &lt;script src="~/lib/jquery/dist/jquery.min.js"&gt;&lt;/script&gt;
    &lt;script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"&gt;&lt;/script&gt;
    &lt;script src="~/js/site.js" asp-append-version="true"&gt;&lt;/script&gt;
    @RenderSection("Scripts", required: false)
&lt;/body&gt;
&lt;/html&gt;

</code></pre>

<h3 id="adding-customer-controller">Adding Customer Controller</h3>

<p>In this part, we are going to add Customer Controller which will be using CustomerViewModel for creating View.</p>

<pre><code class="language-code">
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
namespace WebDemo.Controllers
{
    public class CustomerController : Controller
    {
        [HttpGet]
        public IActionResult Create()
        {
            return View();
        }
    }
}

</code></pre>

<h3 id="adding-customer-view">Adding Customer View</h3>

<p>In this View we are using New Tag Helpers for creating and rendering HTML elements.</p>

<pre><code class="language-code">@model WebDemo.Models.CustomerViewModel
@{
    ViewData["Title"] = "Create";
}

&lt;div class="card"&gt;
    &lt;div class="card-header"&gt;Create&lt;/div&gt;
    &lt;div class="card-body"&gt;
        &lt;form asp-controller="Customer" asp-action="Create" method="post"&gt;
            &lt;div class="form-row"&gt;
                &lt;div class="col"&gt;
                    &lt;label asp-for="FullName"&gt;&lt;/label&gt;
                    &lt;input asp-for="FullName" placeholder="Enter FullName" class="form-control" /&gt;
                    &lt;span asp-validation-for="FullName"&gt;&lt;/span&gt;
                &lt;/div&gt;
                &lt;div class="col"&gt;
                    &lt;label asp-for="City"&gt;&lt;/label&gt;
                    &lt;input asp-for="City" placeholder="Enter City" class="form-control" /&gt;
                    &lt;span asp-validation-for="City"&gt;&lt;/span&gt;
                &lt;/div&gt;
                &lt;div class="col"&gt;
                    &lt;label asp-for="MobileNo"&gt;&lt;/label&gt;
                    &lt;input asp-for="MobileNo" placeholder="Enter MobileNo" class="form-control" /&gt;
                    &lt;span asp-validation-for="MobileNo"&gt;&lt;/span&gt;
                &lt;/div&gt;
            &lt;/div&gt;
            &lt;div class="clearfix"&gt;&lt;/div&gt;
            &lt;div class="form-row"&gt;
                &lt;div class="col"&gt;
               &lt;button style="margin-top: 10px" class="btn btn-success" type="submit"&gt; Submit&lt;/button&gt;
                &lt;/div&gt;
            &lt;/div&gt;
        &lt;/form&gt;
    &lt;/div&gt;
&lt;/div&gt;

</code></pre>
<p>After adding View Now Let’s run application and Test it.</p>

<h3 id="output">Output</h3>

<p><img src="/img/aspdotnetcore/3/11.png" alt="image" /></p>

<p><img src="/img/aspdotnetcore/3/12.png" alt="image" /></p>

<p>Till now, we have seen how to use Localization using DataAnnotations; next, we are going to access the same resources files in Controller and View.</p>

<h3 id="accessing-resources-in-controller-and-view">Accessing Resources in Controller and View</h3>

<p>For accessing the value from the resource file, we are going to create a class with Name <strong>LocalizationService</strong> in Resources Folder.</p>

<p><strong>LocalizationService</strong> class constructor receives an <strong>IStringLocalizerFactory</strong> type parameter which will inject at runtime.</p>

<p><strong>IStringLocalizerFactory Interface</strong>: – Represents a factory that creates <strong>IStringLocalizer</strong> instances.
<strong>IStringLocalizer Interface</strong>: – Represents a service that provides localized strings.</p>

<p><strong>IStringLocalizerFactory</strong> has created a method which takes 2 input</p>

<ul>
  <li>Basename: – basename of resource to load string</li>
  <li>Location: – location to load resources from</li>
</ul>

<p>In our application, we have a base name as <strong>“ApplicationResource”</strong> and location we are going to pass the type name <strong>“ApplicationResource”</strong>.</p>

<p>This class will have Method which will take the key as input and get its value from resource according to Culture.</p>

<pre><code class="language-code">using Microsoft.Extensions.Localization;
using System.Reflection;

namespace WebDemo.Resources
{
    public class LocalizationService
    {
        private readonly IStringLocalizer _localizer;

        public LocalizationService(IStringLocalizerFactory factory)
        {
            var type = typeof(ApplicationResource);
            var assemblyName = new AssemblyName(type.GetTypeInfo().Assembly.FullName!);
            _localizer = factory.Create("ApplicationResource", assemblyName.Name);
        }

        public LocalizedString GetLocalizedHtmlString(string key)
        {
            return _localizer[key];
        }
    }
}

</code></pre>

<h3 id="register-service-in-configureservices-method-in-startup-class">Register service in ConfigureServices Method in Startup class</h3>

<p>We are going to register this service in ConfigureService Method.</p>

<pre><code class="language-code">services.AddSingleton&lt;LocalizationService&gt;();

</code></pre>

<h3 id="accessing-localizationservice-in-controller">Accessing LocalizationService in Controller</h3>

<p><img src="/img/aspdotnetcore/3/13.png" alt="image" /></p>

<h3 id="accessing-localizationservice-on-view">Accessing LocalizationService on View</h3>

<p>For accessing on View, we need to inject LocalizationService on View.</p>

<p>Injecting LocalizationService</p>

<pre><code class="language-code">
@inject LocalizationService LocalizationService

</code></pre>

<p>Accessing Values Using LocalizationService</p>

<pre><code class="language-code">@LocalizationService.GetLocalizedHtmlString("FullName")

</code></pre>

<pre><code class="language-code">
@using WebDemo.Resources
@model CustomerViewModel
@{
    ViewData["Title"] = "Create";
}

@inject LocalizationService LocalizationService

&lt;div class="card"&gt;
    &lt;div class="card-header"&gt;Create&lt;/div&gt;
    &lt;div class="card-body"&gt;
        &lt;form asp-controller="Customer" asp-action="Create" method="post"&gt;
            &lt;div class="form-row"&gt;
                &lt;div class="col"&gt;
                    &lt;label asp-for="FullName"&gt;&lt;/label&gt; | @LocalizationService.GetLocalizedHtmlString("FullName")
                    &lt;input asp-for="FullName" placeholder="Enter FullName" class="form-control" /&gt;
                    &lt;span asp-validation-for="FullName"&gt;&lt;/span&gt;
                &lt;/div&gt;
                &lt;div class="col"&gt;
                    &lt;label asp-for="City"&gt;&lt;/label&gt; | @LocalizationService.GetLocalizedHtmlString("City")
                    &lt;input asp-for="City" placeholder="Enter City" class="form-control" /&gt;
                    &lt;span asp-validation-for="City"&gt;&lt;/span&gt;
                &lt;/div&gt;
                &lt;div class="col"&gt;
                    &lt;label asp-for="MobileNo"&gt;&lt;/label&gt; | @LocalizationService.GetLocalizedHtmlString("MobileNo")
                    &lt;input asp-for="MobileNo" placeholder="Enter MobileNo" class="form-control" /&gt;
                    &lt;span asp-validation-for="MobileNo"&gt;&lt;/span&gt;
                &lt;/div&gt;

            &lt;/div&gt;
            &lt;div class="clearfix"&gt;&lt;/div&gt;
            &lt;div class="form-row"&gt;
                &lt;div class="col"&gt;
                    &lt;button style="margin-top: 10px" class="btn btn-success" type="submit"&gt; Submit&lt;/button&gt;
                &lt;/div&gt;
            &lt;/div&gt;
        &lt;/form&gt;
    &lt;/div&gt;
&lt;/div&gt;
</code></pre>

<h3 id="output-1">Output</h3>

<p><img src="/img/aspdotnetcore/3/14.png" alt="image" /></p>

<h3 id="view-localization">View localization</h3>

<p>The <strong>IViewLocalizer</strong> service provides localized strings for a view. The ViewLocalizer class implements this Interface and finds the resource location from the view file path.</p>

<p>To Use View Localization, we need to create a folder in Resource folder according to your View location which you need to customize.</p>

<p>Take an example we have Views folder inside that Registration folder same we need to create in the Resources folder.</p>

<p><strong>Note: – We have created Registration Controller with Register Action Method in it.</strong></p>

<p><img src="/img/aspdotnetcore/3/15.png" alt="image" /></p>

<p>Inside that folder, we are going to Add resource with the same name as View Name.</p>

<p>If you see above snapshot our View name in Registration folder is Register for that we are going to create resource name as “Register”, and also, we are going to add culture name in the resource file name “Register.en.resx”, “Register.mr.resx”.</p>

<ul>
  <li>en :- English</li>
  <li>hi :- Hindi</li>
</ul>

<p>After creating resource files, we are going insert Key and Values in it.</p>

<p><img src="/img/aspdotnetcore/3/16.png" alt="image" /></p>

<p>Next, we are going to Access this Values on Register View by using <strong>IViewLocalizer</strong>.</p>

<p>Injecting IViewLocalizer in View</p>
<pre><code class="language-code">@inject IViewLocalizer ViewLocalizer
</code></pre>

<h3 id="values-to-access-on-view-using-viewlocalizer">Values to Access on View Using ViewLocalizer</h3>

<pre><code class="language-code">@ViewLocalizer["Name"]
</code></pre>

<h3 id="register-view">Register View</h3>

<pre><code class="language-code">@using Microsoft.AspNetCore.Mvc.Localization
@inject IViewLocalizer ViewLocalizer
@{
    ViewData["Title"] = "Register";
}

&lt;div class="card"&gt;
    &lt;div class="card-body"&gt;
        &lt;form asp-controller="Registration" asp-action="Register" method="post"&gt;
            &lt;div class="form-row"&gt;
                &lt;div class="col"&gt;
                    &lt;label&gt;@ViewLocalizer["Name"]&lt;/label&gt;
                    &lt;input type="text" class="form-control" id="Name"&gt;
                &lt;/div&gt;
                &lt;div class="col"&gt;
                    &lt;label&gt;@ViewLocalizer["City"]&lt;/label&gt;
                    &lt;input type="text" class="form-control" id="City"&gt;
                &lt;/div&gt;
            &lt;/div&gt;
            &lt;div class="clearfix"&gt;&lt;/div&gt;
            &lt;div class="form-row"&gt;
                &lt;div class="col"&gt;
                    &lt;button style="margin-top: 10px" class="btn btn-success" type="submit"&gt; Submit&lt;/button&gt;
                &lt;/div&gt;
            &lt;/div&gt;
        &lt;/form&gt;
    &lt;/div&gt;
&lt;/div&gt;

</code></pre>

<h3 id="output-2">Output</h3>

<p><img src="/img/aspdotnetcore/3/17.png" alt="image" /></p>]]></content><author><name>Girish Godage</name></author><category term="DotnetCore" /><category term="learning" /><summary type="html"><![CDATA[HOW TO IMPLEMENT GLOBALIZATION AND LOCALIZATION IN ASP.NET CORE]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://girishgodage.in/img/aspnetcore.png" /><media:content medium="image" url="https://girishgodage.in/img/aspnetcore.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">HOW TO CROP AND RESIZE IMAGE IN ASP.NET CORE</title><link href="https://girishgodage.in/blog/how-to-crop-and-resize-image-in-asp-net-core" rel="alternate" type="text/html" title="HOW TO CROP AND RESIZE IMAGE IN ASP.NET CORE" /><published>2021-02-14T05:54:00+00:00</published><updated>2021-02-14T05:54:00+00:00</updated><id>https://girishgodage.in/blog/how-to-crop-and-resize-image-in-asp-net-core</id><content type="html" xml:base="https://girishgodage.in/blog/how-to-crop-and-resize-image-in-asp-net-core"><![CDATA[<h2 id="how-to-crop-and-resize-image-in-aspnet-core">HOW TO CROP AND RESIZE IMAGE IN ASP.NET CORE</h2>

<p>In this article, we are going to learn how to Crop and Resize Image and store in a folder in a step by step way.</p>

<p><a href="https://github.com/girishgodage/WebCropper">Github link for Source</a></p>

<p><img src="/img/aspdotnetcore/2/08.png" alt="image" /></p>

<p>Every application we develop now days has the option to set a profile photo right. Some application has a clause of fix length and Size of profile photo where the user needs to upload an image of fix length and Size which cause issues.</p>

<p>In this part we are going allow users to upload a photo then adjust the zoom of the picture as they need then we are going resize Image in different format and store in a folder.</p>

<ul>
  <li>200 * 200   Passport size</li>
  <li>180 * 180   Facebook size</li>
  <li>32 * 32     Icon size</li>
</ul>

<p><img src="/img/aspdotnetcore/2/1.png" alt="image" /></p>

<h3 id="packages-used">Packages Used</h3>

<p><strong>ImageSharp</strong></p>

<p>ImageSharp is a new, fully-featured, fully managed, cross-platform, 2D graphics library. Designed to simplify image processing, ImageSharp brings you an incredibly powerful yet beautifully simple API.</p>

<p><strong>Croppie</strong></p>

<p>Croppie is a fast, easy to use image cropping plugin with tons of configuration options</p>

<h2 id="table-of-contents">Table of Contents</h2>

<ul>
  <li>Getting Started with Upload Crop Resize Image in ASP.NET Core</li>
  <li>Project structure</li>
  <li>Installing SixLabors.ImageSharp Extension from NuGet Package</li>
  <li>Adding Controller and View</li>
  <li>Adding CustomCrop View</li>
  <li>Adding jQuery and Croppie CDN Reference on View</li>
  <li>Initialize Croppie and read file Content</li>
  <li>Adding CustomCrop Post Action Method</li>
  <li>Ajax Request for Posting Cropped Image</li>
  <li>Upload and Cropped Image</li>
  <li>Output</li>
</ul>

<h3 id="getting-started-with-upload-crop-resize-image-in-aspnet-core">Getting Started with Upload Crop Resize Image in ASP.NET Core</h3>

<p>We are going to create a new application with Name WebCropper for demo as shown below.</p>

<p><img src="/img/aspdotnetcore/2/02.png" alt="image" /></p>

<p>Next, we are going to set Project Name “WebCropper” and location. In last part, we are going to choose .</p>

<p>Net Core framework and ASP.NET Core Version 5.0 as the framework for application and few advance settings for such as configuring https and enabling docker we are not going to enable docker settings for this project.</p>

<p><img src="/img/aspdotnetcore/2/03.png" alt="image" /></p>

<p>Now finally click on create button to create a project.</p>

<p><strong>Project structure</strong></p>

<p>The project structure generated according to the configuration.</p>

<p><img src="/img/aspdotnetcore/2/04.png" alt="image" /></p>

<p>After creating project next, we are going to install <strong>SixLabors.ImageSharp</strong> Extension from NuGet Package.</p>

<h3 id="installing-sixlaborsimagesharp-extension-from-nuget-package">Installing SixLabors.ImageSharp Extension from NuGet Package</h3>

<p><img src="/img/aspdotnetcore/2/05.png" alt="image" /></p>

<p>After installing next, we are going to add Controller and View where we will allow uses to upload and crop photo.</p>

<h3 id="adding-controller-and-view">Adding Controller and View</h3>

<p>Let’s Add Controller with name Demo Controller and Action Method with Name CustomCrop.</p>

<pre><code class="language-code">
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;

namespace WebCropper.Controllers
{
    public class DemoController : Controller
    {
        public IActionResult CustomCrop()
        {
            return View();
        }
    }
}

</code></pre>

<p>Next after adding Controller and Action Method next, we are going to add View with Name CustomCrop.</p>

<p>On this View, we are going to add input of type file to upload Image.</p>

<h3 id="adding-customcrop-view">Adding CustomCrop View</h3>

<pre><code class="language-code">@{
    Layout = null;
}

&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;meta name="viewport" content="width=device-width" /&gt;
    &lt;title&gt;CustomCrop&lt;/title&gt;
    &lt;link href="~/lib/bootstrap/dist/css/bootstrap.css" rel="stylesheet" /&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;div class="container"&gt;
        &lt;div class="d-flex justify-content-center"&gt;
            &lt;div class="col-md-6"&gt;

                &lt;div class="card" style="margin-top:10px;"&gt;
                    &lt;div class="card-header"&gt;Cropper in ASP.NET Core&lt;/div&gt;
                    &lt;div class="card-body"&gt;
                        &lt;div id="main-cropper"&gt;&lt;/div&gt;
                        &lt;input type="file" id="select" class="form-control" value="Choose Image" accept="image/*"&gt;
                        &lt;button id="btnupload" style="margin-top: 10px;" name="btnupload" class="btn btn-success"&gt;Crop&lt;/button&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>

<p>Next, after adding View next, we are going to add reference of image cropping plugin.</p>

<h3 id="what-is-croppie">What is Croppie?</h3>

<p>Croppie is a fast, easy to use image cropping plugin with tons of configuration options!</p>

<p>https://foliotek.github.io/Croppie/</p>

<p>Adding jQuery and Croppie CDN Reference on View</p>

<pre><code class="language-code">&lt;head&gt;
  &lt;meta name="viewport" content="width=device-width" /&gt;
  &lt;title&gt;CustomCrop&lt;/title&gt;
  &lt;link href="~/lib/bootstrap/dist/css/bootstrap.css" rel="stylesheet" /&gt;
  &lt;script src="~/lib/jquery/dist/jquery.js"&gt;&lt;/script&gt;
  &lt;link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/croppie/2.6.5/croppie.min.css" /&gt;
  &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/croppie/2.6.5/croppie.min.js"&gt;&lt;/script&gt;
  &lt;style&gt;
        .croppie-container {
            width: 100%;
            height: 80%;
        }
   &lt;/style&gt;
&lt;/head&gt;
</code></pre>

<p>Next, we are going to Initialize croppie.</p>

<pre><code class="language-code">
&lt;script type="text/javascript"&gt;

    //initialize Croppie
    var basic = $('#main-cropper').croppie
    ({
        viewport: { width: 300, height: 300 },
        boundary: { width: 500, height: 400 },
        showZoomer: true,
        url: '/DefaultImages/preview.jpg',
        format:'png' //'jpeg'|'png'|'webp'
    });

    //Reading the contents of the specified Blob or File
    function readFile(input) {
        if (input.files &amp;&amp; input.files[0])
        {
            var reader = new FileReader();

            reader.onload = function (e) {
                $('#main-cropper').croppie('bind', {
                    url: e.target.result
                });
            }
            reader.readAsDataURL(input.files[0]);
        }
    }

   // Change Event to Read file content from File input
    $('#select').on('change', function () { readFile(this); });

&lt;/script&gt;

</code></pre>

<p>After initializing Croppie next, we are going to run the application to see Created UI.</p>

<p><img src="/img/aspdotnetcore/2/06.png" alt="image" /></p>

<p>After we have created UI next let’s create an Action method for handling Ajax POST request.</p>

<h3 id="adding-customcrop-post-action-method">Adding CustomCrop Post Action Method</h3>

<p>In this part, we are going create action method which is going to handle ajax POST request where we are going receive Cropped file.</p>

<p>Reading Stream of Cropped file we are going pass it to ImageSharp Load Method which will return image object on image object we can apply an operation on Image resize a then store in a folder.</p>

<p>We are going to store Image in a folder for that we are going to create a folder in wwwroot with Name Images.</p>

<p>We are going to resize Image in 3 different sizes 200, 180, 32.</p>

<p><img src="/img/aspdotnetcore/2/07.png" alt="image" /></p>

<pre><code class="language-code">
[HttpPost]
        public IActionResult CustomCrop(string filename, IFormFile blob)
        {
            try
            {
                using (var image = Image.Load(blob.OpenReadStream()))
                {
                    string systemFileExtenstion = filename.Substring(filename.LastIndexOf('.'));

                    image.Mutate(x =&gt; x.Resize(180, 180));
                    var newfileName180 = GenerateFileName("Photo_180_180_", systemFileExtenstion);
                    var filepath160 = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "Images")).Root + $@"\{newfileName180}";
                    image.Save(filepath160);

                    var newfileName200 = GenerateFileName("Photo_200_200_", systemFileExtenstion);
                    var filepath200 = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "Images")).Root + $@"\{newfileName200}";
                    image.Mutate(x =&gt; x.Resize(200, 200));
                    image.Save(filepath200);

                    var newfileName32 = GenerateFileName("Photo_32_32_", systemFileExtenstion);
                    var filepath32 = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "Images")).Root + $@"\{newfileName32}";
                    image.Mutate(x =&gt; x.Resize(32, 32));
                    image.Save(filepath32);

                }

                return Json(new { Message = "OK" });
            }
            catch (Exception)
            {
                return Json(new { Message = "ERROR" });
            }
        }

</code></pre>

<p>To generate Unique file name, we have created the below method.</p>

<pre><code class="language-code">
public string GenerateFileName(string fileTypeName, string fileextenstion)
 {
     if (fileTypeName == null) throw new ArgumentNullException(nameof(fileTypeName));
     if (fileextenstion == null) throw new ArgumentNullException(nameof(fileextenstion));
     return $"{fileTypeName}_{DateTime.Now:yyyyMMddHHmmssfff}_{Guid.NewGuid():N}{fileextenstion}";
 }

</code></pre>

<p>After adding CustomCrop action method next, we are going to write XMLHttpRequest request to post filename and file to CustomCrop method.</p>

<h3 id="ajax-request-for-posting-cropped-image">Ajax Request for Posting Cropped Image</h3>

<pre><code class="language-code">// Upload button to Post Cropped Image to Store.
    $('#btnupload').on('click', function ()
    {
        basic.croppie('result', 'blob').then(function (blob)
        {
            var formData = new FormData();

            formData.append('filename', 'FileName.png');
            formData.append('blob', blob);
            var myAppUrlSettings =
            {
                MyUsefulUrl: '@Url.Action("CustomCrop", "Demo")'
            }
            var request = new XMLHttpRequest();
            request.open('POST', myAppUrlSettings.MyUsefulUrl);
            request.send(formData);
            request.onreadystatechange = function () { 
               // Call a function when the state changes.
                if (this.readyState === XMLHttpRequest.DONE &amp;&amp; this.status === 200)
                {
                    var response = JSON.parse(request.responseText);

                    if (response.message == "OK")
                    {
                        alert('Photo Cropped Successfully!');
                        window.location.reload();
                    }
                    if (response.message == "ERROR")
                    {
                        window.location.reload();
                    }
                }
            }
        });
    });
</code></pre>

<p>After adding code for posting cropped images next, let’s run application and test.</p>

<h3 id="upload-and-cropped-image">Upload and Cropped Image</h3>

<p>In this part just upload Image and adjust Image and click on crop button to crop Image.</p>

<p><img src="/img/aspdotnetcore/2/08.png" alt="image" /></p>

<p>After cropping, images will be stored in the folder, as shown below.</p>

<h3 id="output">Output</h3>

<p><img src="/img/aspdotnetcore/2/09.png" alt="image" /></p>]]></content><author><name>Girish Godage</name></author><category term="DotnetCore" /><category term="learning" /><summary type="html"><![CDATA[HOW TO CROP AND RESIZE IMAGE IN ASP.NET CORE]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://girishgodage.in/img/aspnetcore.png" /><media:content medium="image" url="https://girishgodage.in/img/aspnetcore.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">How I choose which services to use in Azure</title><link href="https://girishgodage.in/blog/how-i-choose-AzureService" rel="alternate" type="text/html" title="How I choose which services to use in Azure" /><published>2021-01-07T09:55:00+00:00</published><updated>2021-01-07T09:55:00+00:00</updated><id>https://girishgodage.in/blog/how-i-choose-AzureService</id><content type="html" xml:base="https://girishgodage.in/blog/how-i-choose-AzureService"><![CDATA[<h2 id="introduction">Introduction</h2>

<p>Microsoft Azure is huge and changes fast! I’m impressed by the services and capabilities offered in Azure and by how quickly Microsoft releases new services and features. It can be overwhelming. There is so much out there — and the list continues to grow — it is sometimes hard to know which services to use for a given scenario.</p>

<p>I create Azure solutions for my customers, and I have a <strong>method that I use to help me pick the right services</strong>. This method helps me narrow down the services to choose from and pick the right ones for my solution. It helps me decide how to implement high-level requirements such as <strong>“Running my application in Azure”</strong> or <strong>“Storing data for my application in Azure.”</strong></p>

<p><img src="/img/azure/12/img1.png" alt="image info" /></p>

<p>Of course, these are just examples. There are many other categories to address when I’m architecting an Azure solution.</p>

<h3 id="a-look-at-the-process">A look at the process</h3>

<p>Let me show you the process that I use for <strong>“Running my application in Azure.”</strong></p>

<p>First, I try to answer several high-level questions, which in this case would be:</p>

<p><img src="/img/azure/12/app_process.png" alt="image info" /></p>

<ul>
  <li><strong>1. How much control do I need?</strong></li>
  <li><strong>2. Where do I need my app to run?</strong></li>
  <li><strong>3. What usage model do I need?</strong></li>
  <li><strong>4. Which funcationality do I need?</strong></li>
</ul>

<p>Once I’ve answered these questions, I’ve narrowed down the services from which to choose. And then, I look deeper into the services to see which one best matches the requirements of my application, including functionality as well as availability, performance, and costs.</p>

<p>Let’s go through the first part of the process where I answer the high-level questions about the category.</p>

<h2 id="question-1-how-much-control-do-i-need">Question 1: How much control do I need?</h2>

<p>In considering how much control I need, I try to figure out the degree of control I need over the <strong>operating system, load balancers, infrastructure, application scaling,</strong> and so on. This decides the category of services that I will be selecting from.</p>

<p>On the control side of the spectrum is <strong>infrastructure-as-a-service (IaaS)</strong> category, which includes services like <a href="https://azure.microsoft.com/services/virtual-machines/">Azure Virtual Machines</a> and <a href="https://azure.microsoft.com/services/container-instances/">Azure Container Instances</a>. These give a lot of control over the operating system and the infrastructure that runs your application. But with <span style="color:yellow;background-color:black;"><strong>control comes great responsibility</strong></span>. For instance, if you control the operating system, you are responsible to update it and make sure that it is secure.</p>

<p><img src="/img/azure/12/How_much_control.png" alt="image info" />
<em>Figure 1. How much control do I need?</em></p>

<p>Further up the stack are services that fall into the <strong>platform-as-a-service (PaaS)</strong> category, which contains services like <a href="https://azure.microsoft.com/services/app-service/web/">Azure App Service Web Apps</a>. In PaaS, you don’t have control over the operating system that your application runs on, nor are you responsible for it. You do have control over scaling your application and your application configuration (e.g., the version of .NET you want your application to run on.</p>

<p>The next abstraction level is what I will here call <strong>logic as a service (LaaS)</strong>, also known as <strong>serverless</strong>. This category contains services like <a href="https://azure.microsoft.com/services/functions/">Azure Functions</a> and <a href="https://azure.microsoft.com/services/logic-apps/">Azure Logic Apps</a>. Here, Azure takes care of the underlying infrastructure for you, including scaling your app. Logic as a service gives little control over the infrastructure that your application runs on, which means that you are only responsible for creating the application itself and configuring its application settings, like connection strings to databases.</p>

<p>The highest level of abstraction is <strong>software as a service (SaaS)</strong>, which offers the least amount of control and the most amount of time that you can focus on working on business value. An example of Azure SaaS is <a href="https://azure.microsoft.com/services/cognitive-services/"><strong>Azure Cognitive Services</strong></a>, which are APIs that you just call from your application. Somebody else owns their application code and infrastructure; you just consume them. And all you manage is basic application configuration, like managing the API keys that you use to call the service.</p>

<p>Once I know how much control I need, I can pick the category of services in Azure and narrow down my choice.</p>

<h2 id="question-2-where-do-i-need-my-app-to-run">Question 2: Where do I need my app to run?</h2>

<p>The second question stemming from “Running my application in Azure” is: Where do I need my application to run?</p>

<p><img src="/img/azure/12/Where-my-app-run.png" alt="image info" />
<em>Figure 2. Where do I need my app to run?</em></p>

<p>You might think that the answer would be: I need to run my application in Azure. But the answer may not be that simple. For example, maybe I do want parts of my application to run in the Azure public cloud but I want to run other parts in <a href="https://azure.microsoft.com/global-infrastructure/government/">Azure Government</a> or the Azure China cloud or even on-premises using <a href="https://azure.microsoft.com/overview/azure-stack/">Azure Stack</a>.</p>

<p>Or it could be that I want to be able run my application in Azure and on-premises (if rules and regulations change), on my local development computer, or even in public clouds from other vendors.</p>

<p>This question boils down to how vendor-agnostic I’d like to be and where to store my data.</p>

<p>Once I’ve answered this question, I can narrow down the choice of Azure services even further.</p>

<h2 id="question-3-what-usage-model-do-i-need">Question 3: What usage model do I need?</h2>

<p>How my app will be used guides me to the answer to the third and final question: what usage model do I need?</p>

<p><img src="/img/azure/12/What-useage-model.png" alt="image info" />
<em>Figure 3. What usage model do I need?</em></p>

<p>Some applications <strong>are in use all the time</strong>, like a website. If that is the case for my application, I need to look for services that run on what I call the <strong>classic model</strong>. This means that they are always running and that you pay for them all month.</p>

<p>Other applications <strong>are only in use occasionally</strong>, like a background job that runs once every hour, or an API that handles order cancellations (called a few times a day). If my application runs occasionally, I need to select a service from the logic-as-a-service (or serverless) category. These services only run when you need them, and you only pay for them when they run.</p>

<p>After I’ve answered the high-level questions for this category, I can narrow down the services that I can choose from to just a couple or even one.</p>

<h2 id="question-4-which-functionality-do-i-need">Question 4: Which functionality do I need?</h2>

<p>In this step: We match service functionality to my application requirements</p>

<p>Now, I need to figure out which service fulfills the most requirements for my application. I do so by looking at the functionality that I need, the availability that the service offers in its service level agreement, the performance that it provides, and what it costs.</p>

<p>Finally, this leads me to the service that I want to use to run my application. Often, I use multiple services to run my application, because it consists of many pieces, like a user interface and APIs. So, it might turn out that I run my web application in an Azure App Service Web App and my APIs in Azure Functions.</p>

<h2 id="example-">Example :</h2>

<p>So, let’s just try this out.I have an app, and <strong>I trust Azure to scale for me</strong>.I don’t want to do that myself, <strong>My app needs to run in Azure and on-premises as well</strong>.<strong>As my app only needs to run once every hour</strong>, so not all the time.</p>

<p>My Need to run App.</p>

<ul>
  <li><strong>I trust Azure to scale for me</strong></li>
  <li><strong>My app needs to run in Azure and on-premises as well</strong></li>
  <li><strong>My app only needs to run once every hour</strong></li>
</ul>

<p>So let’s see. These are all the options currently.They’re out there in Azure to run my application.</p>

<p><img src="/img/azure/12/Options_For_Running_App.png" alt="image info" />
<strong>Figure:Option for running Apps on Azure</strong></p>

<p>So, for example, I’m thinking,well, I could just put it into VM,it could be fine, but then I’m paying 24/7 all the time.</p>

<blockquote>
  <p>But My app need are it doesn’t have to be always on.</p>
</blockquote>

<p>I have to remote it to desktop,I have to access or SSH into it and upgrade it.I have to maintain the security.</p>

<blockquote>
  <p>But My app need are Azure to Scale it.</p>
</blockquote>

<p>So, probably not a VM.</p>

<p>Exacty, So, services in the category into infrastructure as a service category,those are not the services that I want in this case.</p>

<p>Also services in the platform as a service category those also need scaling instructions, let’s say.Azure doesn’t do that automatically for me.Yes I can obviously have automatic scaling in a web app,but still I need to think about that and I need to configure it myself.And I don’t want that for this app.</p>

<p>And even I could do Kubernetes and have that scale, but it will be running all the time.</p>

<p>So, I end up in the last category and that is I call it logic Azure service or serverless,and that could be functions or logic apps for instance.
So that’s one category that we’ve drilled down to.</p>

<p><img src="/img/azure/12/img2.png" alt="image info" /></p>

<p>So, that ends up in me being able to work a lot on the business value,and not so much having to worry about the plumbing and infrastructure of a VM for instance.</p>

<p>So, the next thing is,<strong>I want to Stay Vendor Agnostic</strong>. That’s what I said because <strong>it needs to run in Azure but also on premises</strong>.</p>

<p>So, I don’t want to opt in for Azure completely.it needs to run anywhere.In that case, I can choose from these services</p>

<p><img src="/img/azure/12/img3.png" alt="image info" /></p>

<p>including Azure functions because,Azure functions run on the Azure functions run-time.I can run that anywhere basically.</p>

<p>I can take Azure functions as a docker container that I can build from and I could put that on anywhere, on a container locally On-premise Or on my own laptop.Wherever. So, that’s still an options in this case.</p>

<p>Then the next one is I only want to run it occasionally.So not all the time.That’s the serverless,those are Azure Batch,Logic apps and Azure functions.</p>

<p><img src="/img/azure/12/img4.png" alt="image info" /></p>

<p>So, I’m kind of drilling down to Azure functions in this case.For this particular app needs.</p>

<p>Then I will compare all the features of the Azure services to the requirements that I have.I’m not going to drill down into that right now,but I just wanted to show you that I do that in different tables like these.</p>

<p>And I don’t just build a big table,where I just put in all of the Azure services,but just tables that compare one category to another.</p>

<p>For instance, these are all the services for container options and VMs,</p>

<p><span style="color:yellow;background-color:black;"> <strong>Below are the comparision Chart for quick reference</strong></span></p>

<p><img src="/img/azure/12/img5.png" alt="image info" /></p>

<p>and these are all the services for background tasks, will be the one that I need.</p>

<p><img src="/img/azure/12/img6.png" alt="image info" /></p>

<p>And these are all the services for running your application in Azure.</p>

<p><img src="/img/azure/12/img7.png" alt="image info" /></p>

<p>So, that’s my process for choosing how to run an application in Azure.And now the next part is,<strong>how do I store my data in Azure?</strong></p>

<h2 id="storing-data-in-azure">Storing Data in Azure</h2>

<p><img src="/img/azure/12/storing_data.png" alt="image info" /></p>

<blockquote>
  <p>The process that I use for “Storing Data in Azure.”</p>
</blockquote>

<p>How do I do that? Again the same thing.I have a couple of big picture questions that asks to narrow down to services.</p>

<p><img src="/img/azure/12/storing_data_question.png" alt="image info" /></p>

<ul>
  <li><strong>What will I use the data for?</strong></li>
  <li><strong>What type of data am I going to store?</strong></li>
  <li><strong>Which functionality do I need?</strong></li>
</ul>

<p>Once I’ve answered these questions, I’ve narrowed down the services from which to choose. And then, I look deeper into the services to see which one best matches the requirements of my application, including functionality as well as availability, performance, and costs.</p>

<h2 id="question-1-what-will-i-use-the-data-for">Question 1: What will I use the data for?</h2>

<p>So, what will I use the data for? Is it for my application?</p>

<p>So actually for my application,where I have a data stored on my website for instance that stores customer records or something,that’s also called <strong>Online Transactional Processing</strong>.</p>

<p>The other usage that you can imagine is for data analytics, we do reporting.And that’s called <strong>Online Analytical Processing</strong>.</p>

<p><img src="/img/azure/12/What_will_I_use_data_for.png" alt="image info" /></p>

<p>So that’s the first divide that we do.</p>

<h2 id="question-2-what-type-of-data-am-i-going-to-store">Question 2: What type of data am I going to store?</h2>

<p>There are lots of data types.One is Relational Data,another one is Unstructured Data.There are semi-structure data and all that stuff but we’re just going to stick to
these for clarity and simplicity.</p>

<p>In unstructured Data you have different types: Document Data,key Value Data, and Graph Data as well.</p>

<p><img src="/img/azure/12/What_type_of_data.png" alt="image info" /></p>

<p>And then we’re going to try it out,Here is my application data need</p>

<ul>
  <li>
    <p><strong>My app is an online reservation system</strong>.</p>
  </li>
  <li>
    <p><strong>My app needs to store and retrieve document data.</strong></p>
  </li>
</ul>

<p>So that last sentence actually says it all.</p>

<p>For this example, we’re going to focus on the store and retrieve document data in the application.</p>

<p>So, this is again an example of all of the services that are out there right now in Azure for storing data.</p>

<p><img src="/img/azure/12/Options_for_storing_data.png" alt="image info" /></p>

<p>These are things like Azure Sequel Database,Azure storage but also Azure sequel data warehouse.</p>

<p>So the first thing that we’re going to do,is divide this into two categories of data usage.</p>

<p><img src="/img/azure/12/data_category.png" alt="image info" /></p>

<p>So Online Transactional Processing,
so the data storage that I actually
use for my application,
and Online Analytical Processing
data storage that I use for reporting.</p>

<p>So, in our case, it falls into the <strong>first category</strong>,because I want to store and retrieve data for my online reservation system that is online constantly.</p>

<p>And then the second one is, <strong>what type of data</strong>?</p>

<p>So again, these services are relational data,</p>

<p><img src="/img/azure/12/Relational_data.png" alt="image info" /></p>

<p>and these services I can store unstructured or document data and all the other sub types of that.</p>

<p><img src="/img/azure/12/Unstructure_data.png" alt="image info" /></p>

<p>and then these services as a Sequel data warehouse and data lakes store.
I can do data analytics,so I can store big chunks of data and use things like
Power BI or Hadoop Clusters actually crunched that data.</p>

<p><img src="/img/azure/12/data_analytic.png" alt="image info" /></p>

<p>And then after that, I would go into these tables,just like I did for the running the applications,and to see if the requirements match the functionality of the services.</p>

<p><img src="/img/azure/12/data_compare.png" alt="image info" /></p>

<p>And again, I compare services in
different categories like for OLAP and OLTP in this case.</p>

<p><img src="/img/azure/12/data_compare1.png" alt="image info" /></p>

<p>So that’s my process basically.</p>

<p>So, these were just a couple
of services in the Azure space,
just for running your application and for storing data.</p>

<p>Obviously, there are lot of more services out there for securing your application and for doing IoT and all that stuff.</p>]]></content><author><name>Girish Godage</name></author><category term="AzureCloud" /><category term="learning" /><summary type="html"><![CDATA[Introduction]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://girishgodage.in/img/azure/12/img1.png" /><media:content medium="image" url="https://girishgodage.in/img/azure/12/img1.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Facebook Authentication And Authorization In Server-Side Blazor App</title><link href="https://girishgodage.in/blog/facebook-authentication-and-authorization-in-server-side-blazor-app" rel="alternate" type="text/html" title="Facebook Authentication And Authorization In Server-Side Blazor App" /><published>2020-12-20T09:46:00+00:00</published><updated>2020-12-20T09:46:00+00:00</updated><id>https://girishgodage.in/blog/facebook-authentication-and-authorization-in-server-side-blazor-app</id><content type="html" xml:base="https://girishgodage.in/blog/facebook-authentication-and-authorization-in-server-side-blazor-app"><![CDATA[<h2 id="introduction">Introduction</h2>

<p>In this article, we will learn how to implement authentication and authorization using Facebook in a server-side Blazor application.</p>

<h2 id="prerequisites">Prerequisites</h2>
<ul>
  <li>Install the latest .NET Core 5.0 Current  SDK from <a href="https://dotnet.microsoft.com/download/dotnet-core/">here</a>.</li>
  <li>Install the latest Visual Studio 2019 from <a href="https://visualstudio.com/">here</a>.</li>
</ul>

<h2 id="source-code">Source Code</h2>

<p>Get the source code from <a href="https://github.com/girishgodage/Facebook-Authentication-with-server-side-Blazor">GitHub</a>.</p>

<h2 id="create-server-side-blazor-application">Create Server Side Blazor Application</h2>

<p>To create a server-side Blazor app, open Visual Studio 2019 and follow the steps mentioned below:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>1. Click on “Create a new project”.
2. Select “Blazor App” from available project types. Click on Next.
3. A new “Configure your new project” screen will open. Put the name of the project as BlazorFbAuth and click Create.
4. In the next screen, select “.NET.5.0 ” from dropdowns on the top left.
5. Select “Blazor Server App” from the list of available templates.
6. Click on Change Authentication button, a “Change Authentication” dialog box will open.
7.Select “Individual User Account” and click OK. Click on Create button to create the application.
</code></pre></div></div>

<p>These steps are shown in the GIF image below.</p>

<p><img src="/img/blazor/5/CreateProject.gif" alt="image info" /></p>

<p>Before running the application, we need to apply migrations to our app. Navigate to Tools » NuGet Package Manager » Package Manager Console.</p>

<p>It will open the Package Manager Console. Put in <strong>Update-Database</strong> command and hit enter. This will update the database using Entity Framework Code First Migrations.</p>

<p><img src="/img/blazor/5/UpdateDatabase.png" alt="image info" /></p>

<p>Right-click on the project in solution explorer and select properties. Select Debug from left side menu then scroll to the bottom of the page. Note the SSL enabled URL. In this case, the URL is https://localhost:44345/. We need this URL to configure the Facebook app which we will be doing in our next section. Refer to the image below.</p>

<p><img src="/img/blazor/5/AppURL.png" alt="image info" /></p>

<h2 id="creating-a-facebook-app">Creating a Facebook App</h2>

<p>We need to create a Facebook app and configure Facebook Login for it. We will then use the App ID and App Secret of this Facebook app to implement Facebook authentication in our Blazor app. Navigate to https://developers.facebook.com/apps/ and sign in using your Facebook account. Follow the steps mentioned below.</p>

<ul>
  <li>Click on the “Create App” button under the “My Apps” menu on the top.</li>
  <li>It will open a “Create a New App ID” dialog box. Put in the “Display Name” and “Contact Email”.</li>
  <li>The default email will be your Facebook email id. However, you can change it and put any email of your choice. Click on “Create App ID” to create the app. Refer to the image below.</li>
</ul>

<p><img src="/img/blazor/5/BlazorFBAuthAppInfo.png" alt="image info" /></p>

<ul>
  <li>Navigate to the app dashboard by clicking on the “Dashboard” link on the navigation menu on the left.</li>
  <li>Under the “Add a Product” section, select the “Facebook Login” product and click on “Set Up” button.</li>
  <li>A QuickStart wizard will be launched asking you to select a platform for the app. Skip this wizard and click on Facebook Login &gt; Settings from the navigation menu on the left.</li>
  <li>You will be navigated to the Client OAuth Settings page. In the Valid OAuth redirect URIs field enter the base URL of your application with /signin-facebook appended to it. For this tutorial, the URL will be https://localhost:44345/signin-facebook. Click on “Save Changes” button.</li>
  <li>Now click on Settings &gt; Basic on the navigation menu. You will see the App ID and App Secret values. Make a note of these values as we need them to configure Facebook authentication in our Blazor app.</li>
</ul>

<p>Refer to the GIF below for a better understanding.</p>

<p><img src="/img/blazor/5/FBSettings.gif" alt="image info" /></p>

<h2 id="important-note">Important Note</h2>

<blockquote>
  <p>The trademark or brand element of Facebook is not allowed to be used as the Display Name of your Facebook App. Therefore, words such as FB, Face, Book, Insta, etc. cannot be used as Display Name.</p>
</blockquote>

<h2 id="installing-facebook-authentication-middleware-nuget-package">Installing Facebook authentication middleware NuGet package</h2>

<p>To configure the ASP.NET Core middleware for Facebook authentication we need to install the nuget package in our application. The version of this nuget package must match the version of .NET Core 3 which we are using in our project.</p>

<p>Open https://www.nuget.org/packages/Microsoft.AspNetCore.Authentication.Facebook/. Select the version of .NET 5.0.1 from the “Version History”. Copy the command from the “package manager” tab. Run this command in the NuGet package manager console of our application.</p>

<p>For this application, we are using .NET 5.0.1. Therefore, we will run the following command in the package manager console of our application.</p>

<pre><code class="language-code">    Install-Package Microsoft.AspNetCore.Authentication.Facebook -Version 5.0.1
</code></pre>

<p>Refer to the image below:</p>

<p><img src="/img/blazor/5/InstallFBAuthentication.png" alt="image info" /></p>

<h2 id="configure-the-server-side-blazor-app-to-use-facebook-authentication">Configure the server-side Blazor app to use Facebook authentication</h2>

<p>We need to store the App ID and App Secret field values in our application. We will use Secret Manager tool for this purpose. The Secret Manager tool is a project tool that is used to store secrets such as password, API Key, etc. for a .NET Core project during the development process. Secret Manager tool allows us to associate app secrets with a specific project. It also allow us to share them across multiple projects.</p>

<p>Open our web application once again and Right-click the project in Solution Explorer. Select Manage User Secrets from the context menu. A secrets.json file will open. Put the following code in it.</p>

<pre><code class="language-code">    {
        "Authentication:Facebook:AppId": "Your Facebook AppId",
        "Authentication:Facebook:AppSecret": "Your Facebook AppSecret"
    }
</code></pre>

<p>Now open Startup.cs file and put the following code into ConfigureServices method.</p>

<pre><code class="language-code">
    services.AddAuthentication().AddFacebook(facebookOptions =&gt;
    {
        facebookOptions.AppId = Configuration["Authentication:Facebook:AppId"];
        facebookOptions.AppSecret = Configuration["Authentication:Facebook:AppSecret"];
        facebookOptions.Events = new OAuthEvents()
        {
            OnRemoteFailure = loginFailureHandler =&gt;
            {
            var authProperties = facebookOptions.StateDataFormat.Unprotect(loginFailureHandler.Request.Query["state"]);
            loginFailureHandler.Response.Redirect("/Identity/Account/Login");
            loginFailureHandler.HandleResponse();
            return Task.FromResult(0);
            }
        };
    });
</code></pre>

<p>This code will read the AppId and AppSecret from the secrets.json file. The AddFacebook() method is an extension method and it is used to configure the Facebook Authentication options for our application. We are also handling the event of OnRemoteFailure in this code section. Hence, if the user denies access to his Facebook account, then he will be redirected back to the Login page of our Blazor application.</p>

<h2 id="adding-authorization-to-blazor-pages">Adding authorization to Blazor pages</h2>

<p>Blazor has added a new built-in component called AuthorizeView. This component is used to display different content based on the authentication state of the application. This component will display the child component only when the user is authorized.  The AuthorizeView component is configured in \Shared\LoginDisplay.razor file.</p>

<p>To implement authorization to a specific page, we need to use the [Authorize] attribute. Blazor has introduced a new directive @attribute, which is used to include the [Authorize] attribute for a page. In this application, we will apply [Authorize] to the FetchData component. This will prohibit unauthorized access to this component. Open FetchData.razor page and add the following lines at the top of the page.</p>

<pre><code class="language-code">
@attribute [Authorize]

</code></pre>

<h2 id="execution-demo">Execution Demo</h2>

<p>Launch the application. Navigate to Fetch Data component by clicking on the “Fetch data” link on the menu on the left. You will see a “Not authorized” message displayed on the screen. Click “Log In” on the menu at the top. In the next page click on the “Facebook” button to login with Facebook. On the next page, you will be asked to provide the login credentials of your Facebook account. Fill the details and click Log In. Upon successful login, you will be able to access the Fetch Data component. If you do not want to login then click on “Not now”. It will redirect you back to the Login page of Blazor app.</p>

<p>Refer to the GIF below for a better understanding.</p>

<p><img src="/img/blazor/5/output.gif" alt="image info" /></p>

<p>Once you are logged in successfully into our Blazor app using Facebook, you will be also logged in to https://www.facebook.com/. This will create a set of browser cookie for https://www.facebook.com/. Therefore, the Blazor app will not ask the Facebook credentials when you try to login again. If you log out from Facebook then you have to enter credentials while logging into Blazor app.</p>

<h2 id="conclusion">Conclusion</h2>

<p>We learned how to implement Facebook authentication and authorization in a server-side Blazor application. We have created and configured a Facebook app to implement Facebook authentication. To implement authorization for a specific component in Blazor, we have used the [Authorize] attribute. We have used Microsoft.AspNetCore.Authentication.Facebook nuget package to configure the middleware for Facebook authentication.</p>

<p>Please get the source code from <a href="https://github.com/girishgodage/Facebook-Authentication-with-server-side-Blazor">GitHub</a> and play around to get a better understanding.</p>]]></content><author><name>Girish Godage</name></author><category term="Blazor" /><category term="Azure" /><category term="learning" /><summary type="html"><![CDATA[Introduction]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://girishgodage.in/img/blazor/5/output.gif" /><media:content medium="image" url="https://girishgodage.in/img/blazor/5/output.gif" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">How to Deploy Angular Application to Heroku</title><link href="https://girishgodage.in/blog/how-to-deploy-angular-application-to-heroku" rel="alternate" type="text/html" title="How to Deploy Angular Application to Heroku" /><published>2020-12-20T09:46:00+00:00</published><updated>2020-12-20T09:46:00+00:00</updated><id>https://girishgodage.in/blog/deploy-angular-on-Heroku</id><content type="html" xml:base="https://girishgodage.in/blog/how-to-deploy-angular-application-to-heroku"><![CDATA[<h2 id="introduction">Introduction</h2>

<p>It has always ‘seemed’ easy until you try it. Having deployed other apps to heroku, I encountered series of challenges deploying Angular 11 recently but I pulled through finally. So am writing to explain in details how I did it.</p>

<p>This article will show you guides on deploying your Angular 8/9/10/11 apps easily to Heroku, more importantly, avoiding common pitfalls.</p>

<p>This is not a tutorial to help you learn Angular. It will be assumed you have completed development and ready to deploy. However, we’ll setup basic angular project from start and deploy. This tutorial will cover:</p>

<ul>
  <li>Creating basic angular project</li>
  <li>Setting automatic deployment from GitHub to Heroku</li>
  <li>Deploying Angular app on Heroku server</li>
</ul>

<h2 id="setup-your-angular-application">Setup Your Angular Application</h2>
<p>Making use of the Angular CLI, setup a new project by running:</p>
<pre><code class="language-code">
    ng new demo-deploy

</code></pre>

<p><img src="/img/deployment/1/CreateAngularApp.png" alt="image info" /></p>

<p>From this, our application will be named demo-deploy . Allow for few minutes to setup the new project and install npm packages.</p>

<h2 id="launch-application">Launch Application</h2>

<p>Change directory into new project and launch it using the commands below. This will open in new browser on port 4200 by default. i.e http://localhost:4200.</p>

<pre><code class="language-code">cd demo-deploy
ng serve

</code></pre>

<p><img src="/img/deployment/1/angularapp.png" alt="image info" /></p>

<p>Our basic angular app is ready and running — locally. Lets push to github</p>

<h2 id="create-its-github-repo-and-push">Create its GitHub repo and Push</h2>
<p>Here, we’ll be creating a fresh github repository and pushing our app to it.</p>

<ul>
  <li>
    <p>Login to github and create new repository. No need to initialize repository with README</p>
  </li>
  <li>
    <p>Open new tab in your terminal/CMD. Or hit Ctrl+C to stop running app. Then run the following commands:</p>
  </li>
</ul>

<pre><code class="language-code">
    git remote add origin &lt;new_github_repository_url&gt;
    git add --all
    git commit -m "initial commit"
    git push -u origin master

</code></pre>

<p>Now our app is on github.</p>

<h2 id="setup-automatic-deployment-from-github-to-heroku">Setup Automatic Deployment from GitHub to Heroku</h2>

<p>Advantage of this step is so that, once you push a change to your github repository, it automatically pushes the change to your codebase on heroku, which then takes effect live on the web. This means, you’ll only have to push your changes to github and its done.</p>

<p>If you dont have an account yet, create one on heroku website. Its free. Login to your dashboard and create a new app.</p>

<p><img src="/img/deployment/1/CreateHerokuapp.png" alt="image info" /></p>

<p>Click Create app</p>

<p>In the Deploy menu, under Deployment method, select GitHub. If you have not done this already, it will ask you to login your github account so it can connect to it.</p>

<p>Enter the name of the GitHub repository and click Search. Once the repo is shown below, click Connect. Viola!</p>

<p><img src="/img/deployment/1/HerokuGithubConnect.png" alt="image info" /></p>

<p>Uh, wait. Two more simple steps.</p>

<ol>
  <li>
    <p>Under Automatic Deploys, select the master branch and click Enable Automatic Deploys.</p>
  </li>
  <li>
    <p>Under Manual Deploys, click Deploy Branch. This is to push our fresh code to heroku.</p>
  </li>
</ol>

<p><img src="/img/deployment/1/EnableAutoDeploy.png" alt="image info" /></p>

<p>Okay, we’r done with this stage really. It might take a little while but will show you successfully deployed message once done, like so:</p>

<p><img src="/img/deployment/1/DeployGithubBranch.png" alt="image info" /></p>

<p><img src="/img/deployment/1/DeployError.png" alt="image info" /></p>

<p>If you click View, a new tab will be opened but your app will not display. Next series of steps will guide you on configuring and spinning up your angular app.</p>

<h2 id="configure-your-angular-app-to-deploy-properly-on-heroku">Configure Your Angular App to Deploy Properly on Heroku</h2>

<p>The following are production-ready steps to easily and properly deploy your app without hitches.</p>

<blockquote>
  <p><strong>Ensure you have the latest version of angular cli and angular compiler cli</strong>.</p>
</blockquote>

<p>Install them into your application by running this commands in your terminal:</p>

<pre><code class="language-code">npm install @angular/cli@latest @angular/compiler-cli --save-dev

</code></pre>

<p>In your package.json, copy</p>

<pre><code class="language-code">
"@angular/cli”: “~11.0.5”,
"@angular/compiler-cli": "~11.0.5",

</code></pre>

<p>from devDependencies to dependencies</p>

<h2 id="create-postinstall-script-in-packagejson">Create postinstall script in package.json</h2>

<p>Under “scripts”, add a “heroku-postinstall” command like so:</p>

<pre><code class="language-code">"heroku-postbuild": "ng build --aot --prod "

</code></pre>

<p>This tells Heroku to build the application using Ahead Of Time (AOT) compiler and make it production-ready. This will create a dist folder where all html and javascript converted version of our app will be launched from.</p>

<h2 id="add-node-and-npm-engines">Add Node and NPM engines</h2>

<p>You will need to add the Node and NPM engines that Heroku will use to run your application. Preferably, it should be same version you have on your machine. So, run <em>node -v</em> and <em>npm -v</em> to get the correct version and include it in your package.json file like so:</p>

<pre><code class="language-code">
    "engines": {
    "node": "15.2.0",
    "npm": "7.0.12"
  }

</code></pre>

<h2 id="copy-typescript-to-dependencies">Copy typescript to dependencies.</h2>

<p>Copy “typescript”: “~4.0.2” from devDependencies to dependencies to also inform Heroku what typescript version to use.</p>

<h2 id="install-enhanced-resolve-330">Install Enhanced Resolve 3.3.0</h2>

<p>Run the command <strong>npm install enhanced-resolve@3.3.0 –save-dev</strong></p>

<h2 id="install-server-to-run-your-app">Install Server to run your app</h2>

<p>Locally we run ng serve from terminal to run our app on local browser. But we will need to setup an Express server that will run our production ready app (from dist folder created) only to ensure light-weight and fast loading.</p>

<p>Install Express server by running:</p>

<pre><code class="language-code">
npm install express path --save

</code></pre>

<p>Create a server.js file in the root of the application and paste the following code.</p>

<pre><code class="language-code">
    //Install express server
    const express = require('express');
    const path = require('path');

    const app = express();

    // Serve only the static files form the dist directory
    app.use(express.static(__dirname + '/dist/&lt;name-of-app&gt;'));

    app.get('/*', function(req,res) {
        
    res.sendFile(path.join(__dirname+'/dist/&lt;name-of-app&gt;/index.html'));
    });

    // Start the app by listening on the default Heroku port
    app.listen(process.env.PORT || 8080);

</code></pre>

<h2 id="change-start-command">Change start command</h2>

<p>In package.json, change the “start” command to node server.js so it becomes:</p>

<pre><code class="language-code">
    "start": "node server.js"

</code></pre>

<p>Here’s what the complete package.json looks like. Yours may contain more depending on your application-specific packages.</p>

<pre><code class="language-code">
{
  "name": "demo-deploy",
  "version": "0.0.0",
  "scripts": {
    "ng": "ng",
    "start": "node server.js",
    "build": "ng build",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e",
    "heroku-postbuild": "ng build --aot --prod "
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "~11.0.5",
    "@angular/cdk": "^11.0.3",
    "@angular/cli": "~11.0.5",
    "@angular/common": "~11.0.5",
    "@angular/compiler": "~11.0.5",
    "@angular/compiler-cli": "~11.0.5",
    "@angular/core": "~11.0.5",
    "@angular/forms": "~11.0.5",
    "@angular/platform-browser": "~11.0.5",
    "@angular/platform-browser-dynamic": "~11.0.5",
    "@angular/router": "~11.0.5",
    "express": "^4.17.1",
    "path": "^0.12.7",
    "rxjs": "~6.6.0",
    "tslib": "^2.0.0",
    "typescript": "~4.0.2",
    "zone.js": "~0.10.2"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "~0.1100.5",
    "@angular/cli": "~11.0.5",
    "@angular/compiler-cli": "~11.0.5",
    "@types/googlemaps": "3.39.14",
    "@types/jasmine": "~3.6.0",
    "@types/node": "^12.11.1",
    "codelyzer": "^6.0.0",
    "enhanced-resolve": "^3.3.0",
    "jasmine-core": "~3.6.0",
    "jasmine-spec-reporter": "~5.0.0",
    "karma": "~5.1.0",
    "karma-chrome-launcher": "~3.1.0",
    "karma-coverage": "~2.0.3",
    "karma-jasmine": "~4.0.0",
    "karma-jasmine-html-reporter": "^1.5.0",
    "protractor": "~7.0.0",
    "ts-node": "~8.3.0",
    "tslint": "~6.1.0",
    "typescript": "~4.0.2"
  },
  "engines": {
    "node": "15.2.0",
    "npm": "7.0.12"
  }
}

</code></pre>

<p>Push changes to GitHub:</p>

<pre><code class="language-code">
    git add .
    git commit -m "updates to deploy to heroku"
    git push  

</code></pre>

<p>At this point, your application on Heroku will automatically take the changes from GitHub and update itself.</p>

<p>Also, it’ll look into your package.json and install packages.</p>

<p>It will run the postinstall and then, <em>node server.js</em> to spin up your application.</p>

<p>You can check Activity tab and open Build log to see how it actually runs.</p>

<p>You should not run into any issue. I followed through while writing this post also and.</p>

<p>Viola!! Our Angular app is Ready and LIVE!</p>

<p><img src="/img/deployment/1/DeployedApp.png" alt="image info" /></p>

<p>For following through till this stage, Thank you.</p>

<p>Provide your valuable comment below, also if you encountered any issue or want to suggest better ways.</p>]]></content><author><name>Girish Godage</name></author><category term="Deployment" /><category term="learning" /><summary type="html"><![CDATA[Introduction]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://girishgodage.in/img/deployment/1/AnularDeployHeroku.png" /><media:content medium="image" url="https://girishgodage.in/img/deployment/1/AnularDeployHeroku.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Multi-Language Translator Using Blazor And Azure Cognitive Services</title><link href="https://girishgodage.in/blog/multi-Language-Translator-using-blazor-AzureCognitiveServices" rel="alternate" type="text/html" title="Multi-Language Translator Using Blazor And Azure Cognitive Services" /><published>2020-12-17T16:55:00+00:00</published><updated>2020-12-17T16:55:00+00:00</updated><id>https://girishgodage.in/blog/multi-language-translator-using-blazor-and-azure-cognitive-service</id><content type="html" xml:base="https://girishgodage.in/blog/multi-Language-Translator-using-blazor-AzureCognitiveServices"><![CDATA[<h2 id="introduction">Introduction</h2>

<p>In this article, we will create a multilanguage translator using Blazor and the Translate Text Azure Cognitive Service. This translator will be able to translate between all the languages supported by the Translate Text API. Currently, the Translate Text API supports more than 60 languages for translation. The application will accept the text to translate and the target language as the input and returns the translated text and the detected language for the input text as the output.</p>

<p>Take a look at the output shown below.</p>

<p><img src="/img/azure/11/output.gif" alt="image info" /></p>

<h2 id="prerequisites">Prerequisites</h2>
<ul>
  <li>Install the latest .NET Core 3.1 SDK from https://dotnet.microsoft.com/download/dotnet-core/3.1</li>
  <li>Install the latest version of Visual Studio 2019 from https://visualstudio.microsoft.com/downloads/</li>
  <li>An Azure subscription account. You can create a free Azure account  at https://azure.microsoft.com/en-in/free/</li>
</ul>

<h2 id="source-code">Source Code</h2>
<p>You can get the source code from <a href="https://github.com/girishgodage/Blazor-Translator-Azure-Cognitive-Services">GitHub</a>.</p>

<h2 id="create-the-azure-translator-text-cognitive-services-resource">Create the Azure Translator Text Cognitive Services resource</h2>

<p>Log in to the Azure portal and search for the cognitive services in the search bar and click on the result. Refer to the image shown below.</p>

<p><img src="/img/azure/9/SearchCognitive.png" alt="image info" /></p>

<p>On the next screen, click on the Add button. It will open the cognitive services marketplace page. Search for the Translator Text in the search bar and click on the search result. It will open the Translator Text API page. Click on the Create button to create a new Translator Text resource. Refer to the image shown below.</p>

<p><img src="/img/azure/11/CreateTranslatorService.png" alt="image info" /></p>

<p>On the Create page, fill in the details as indicated below.</p>

<ul>
  <li><strong>Name</strong>: Give a unique name for your resource.</li>
  <li><strong>Subscription</strong>: Select the subscription type from the dropdown.</li>
  <li><strong>Pricing tier</strong>: Select the pricing tier as per your choice.</li>
  <li><strong>Resource group</strong>: Select an existing resource group or create a new one.</li>
</ul>

<p>Click on the Create button. Refer to the image shown below.</p>

<p><img src="/img/azure/11/CreateTranslatorService_1.png" alt="image info" /></p>

<p><img src="/img/azure/11/CreateTranslatorService_2.png" alt="image info" /></p>

<p>After your resource is successfully deployed, click on the “Go to resource” button. You can see the Key and the endpoint for the newly created Computer Vision resource. Refer to the image shown below.</p>

<p><img src="/img/azure/11/TranslatorKeyNEndPoint.png" alt="image info" /></p>

<p>Make a note of the <strong>key</strong>, we will be using this in the latter part of this article to request the translations from the Translator Text API. The values are masked here for privacy.</p>

<h2 id="create-a-server-side-blazor-application">Create a Server-Side Blazor Application</h2>

<p>Open Visual Studio 2019, click on “Create a new project”. Select “Blazor App” and click on the “Next” button. Refer to the image shown below.</p>

<p><img src="/img/azure/10/Create_BlazorApp.png" alt="image info" /></p>

<p>On the next window, put the project name as <span style="color:yellow;background-color:black;">BlazorTranslator</span> and click on the “Create” button. The next window will ask you to select the type of Blazor app. Select <span style="color:yellow;background-color:black;">Blazor Server App </span> and click on the Create button to create a new server-side Blazor application. Refer to the image shown below.</p>

<p><img src="/img/azure/10/Create_BlazorApp_1.png" alt="image info" /></p>

<h2 id="create-the-models">Create the Models</h2>

<p>Right-click on the <span style="color:yellow;background-color:black;">BlazorTranslator</span> project and select Add » New Folder. Name the folder as Models. Again, right-click on the Models folder and select Add » Class to add a new class file. Put the name of your class as <span style="color:yellow;background-color:black;">LanguageDetails.cs</span> and click Add.</p>

<p>Open <span style="color:yellow;background-color:black;">LanguageDetails.cs</span> and put the following code inside it.</p>

<pre><code class="language-code"> namespace BlazorTranslator.Models
{
    public class LanguageDetails
    {
        public string Name { get; set; }
        public string NativeName { get; set; }
        public string Dir { get; set; }
    }
}

</code></pre>

<p>Similarly, add a new class file <span style="color:yellow;background-color:black;">TestResult.cs </span> and put the following code inside it.</p>

<pre><code class="language-code"> using System;
namespace BlazorTranslator.Models
{
    public class TextResult
    {
        public string Text { get; set; }
        public string Script { get; set; }
    }
}

</code></pre>

<p>Add a new class file Translation.cs and put the following code inside it.</p>

<pre><code class="language-code">
    namespace BlazorTranslator.Models
    {
        public class Translation
        {
            public string Text { get; set; }
            public TextResult Transliteration { get; set; }
            public string To { get; set; }
        }
    }

</code></pre>

<p>Create a class file <span style="color:yellow;background-color:black;">DetectedLanguage.cs</span> and put the following code inside it.</p>

<pre><code class="language-code">    namespace BlazorTranslator.Models
    {
        public class DetectedLanguage
        {
            public string Language { get; set; }
            public float Score { get; set; }
        }
    }

</code></pre>

<p>Create a class file <span style="color:yellow;background-color:black;">TranslationResult.cs</span> and put the following code inside it.</p>

<pre><code class="language-code">
    namespace BlazorTranslator.Models
    {
        public class TranslationResult
        {
            public DetectedLanguage DetectedLanguage { get; set; }
            public TextResult SourceText { get; set; }
            public Translation[] Translations { get; set; }
        }
    }

</code></pre>

<p>Finally, create the class file <span style="color:yellow;background-color:black;">AvailableLanguage.cs</span> and put the following code inside it.</p>

<pre><code class="language-code">    using System.Collections.Generic;
    namespace BlazorTranslator.Models
    {
        public class AvailableLanguage
        {
        public Dictionary&lt;string, LanguageDetails&gt; Translation { get; set; }
        }
    }

</code></pre>

<h2 id="create-the-translation-service">Create the Translation service</h2>

<p>Right-click on the <span style="color:yellow;background-color:black;">BlazorTranslator/Data</span> folder and select Add » Class to add a new class file. Put the name of the file as <span style="color:yellow;background-color:black;">TranslationService.cs</span> and click on Add. Open <span style="color:yellow;background-color:black;">TranslationService.cs</span> file and put the following code inside it.</p>

<pre><code class="language-code">
    using BlazorTranslator.Models;
    using Newtonsoft.Json;
    using System;
    using System.Net.Http;
    using System.Text;
    using System.Threading.Tasks;
    namespace BlazorTranslator.Data
    {
        
        public class TranslationService
        {
            private static readonly string location = "eastus";
            
            public async Task&lt;TranslationResult[]&gt; GetTranslatation(string textToTranslate, string targetLanguage)
            {
                string subscriptionKey = "52937b775b454b65830ac59e5dc22d9d";
                string apiEndpoint = "https://api.cognitive.microsofttranslator.com/";
                string route = $"/translate?api-version=3.0&amp;to={targetLanguage}";
                string requestUri = apiEndpoint + route;
                TranslationResult[] translationResult = await TranslateText(subscriptionKey, requestUri, textToTranslate);
                return translationResult;
            }
            async Task&lt;TranslationResult[]&gt; TranslateText(string subscriptionKey, string requestUri, string inputText)
            {
                object[] body = new object[] { new { Text = inputText } };
                var requestBody = JsonConvert.SerializeObject(body);
                using (var client = new HttpClient())
                using (var request = new HttpRequestMessage())
                {
                    request.Method = HttpMethod.Post;
                    request.RequestUri = new Uri(requestUri);
                    request.Content = new StringContent(requestBody, Encoding.UTF8, "application/json");
                    request.Headers.Add("Ocp-Apim-Subscription-Key", subscriptionKey);
                    request.Headers.Add("Ocp-Apim-Subscription-Region", location);
                    HttpResponseMessage response = await client.SendAsync(request).ConfigureAwait(false);
                    string result = await response.Content.ReadAsStringAsync();
                    TranslationResult[] deserializedOutput = JsonConvert.DeserializeObject&lt;TranslationResult[]&gt;(result);
                    return deserializedOutput;
                }
            }
            public async Task&lt;AvailableLanguage&gt; GetAvailableLanguages()
            {
                string endpoint = "https://api.cognitive.microsofttranslator.com/languages?api-version=3.0&amp;scope=translation";
                var client = new HttpClient();
                using (var request = new HttpRequestMessage())
                {
                    request.Method = HttpMethod.Get;
                    request.RequestUri = new Uri(endpoint);
                    var response = await client.SendAsync(request).ConfigureAwait(false);
                    string result = await response.Content.ReadAsStringAsync();
                    AvailableLanguage deserializedOutput = JsonConvert.DeserializeObject&lt;AvailableLanguage&gt;(result);
                    return deserializedOutput;
                }
            }
        }
    }

</code></pre>

<p>We have defined a <span style="color:yellow;background-color:black;">GetTranslatation</span> method which will accept two parameters – the text to translate and the target language. We will set the subscription key for the Azure Translator Text cognitive service and define a variable for the global endpoint for Translator Text. The request URL contains the API endpoint along with the target language.</p>

<p>Inside the <span style="color:yellow;background-color:black;">TranslateText</span> method, we will create a new <span style="color:yellow;background-color:black;">HttpRequestMessage</span>. This HTTP request is a Post request. We will pass the subscription key in the header of the request. The Translator Text API returns a JSON object, which will be deserialized to an array of type <span style="color:yellow;background-color:black;">TranslationResult</span>. The output contains the translated text as well as the language detected for the input text.</p>

<p>The <span style="color:yellow;background-color:black;">GetAvailableLanguages</span> method will return the list of all the language supported by the Translate Text API. We will set the request URI and create a <span style="color:yellow;background-color:black;">HttpRequestMessage</span> which will be a Get request. This request URL will return a JSON object which will be deserialized to an object of type <span style="color:yellow;background-color:black;">AvailableLanguage</span>.</p>

<h2 id="configuring-the-service">Configuring the Service</h2>

<p>To make the service available to the components we need to configure it on the server-side app. Open the <span style="color:yellow;background-color:black;">Startup.cs file</span>. Add the following line inside the <span style="color:yellow;background-color:black;">ConfigureServices</span> method of Startup class.</p>

<pre><code class="language-code">
    services.AddSingleton&lt;TranslationService&gt;();

</code></pre>

<h2 id="creating-the-blazor-ui-component">Creating the Blazor UI Component</h2>

<p>We will add the Razor page in the <span style="color:yellow;background-color:black;">BlazorTranslator/Pages</span> folder. By default, we have “Counter” and “Fetch Data” pages provided in our application. These default pages will not affect our application but for the sake of this tutorial, we will delete fetchdata and counter pages from <span style="color:yellow;background-color:black;">BlazorTranslator/Pages</span> folder.</p>

<p>Right-click on the <span style="color:yellow;background-color:black;">BlazorTranslator/Pages folder</span> and then select Add » New Item. An “Add New Item” dialog box will open, select “Visual C#” from the left panel, then select “Razor Component” from the templates panel, put the name as <span style="color:yellow;background-color:black;">Translator.razor</span>. Click Add. Refer to the image shown below.</p>

<p><img src="/img/azure/11/AddBlazorComponet.png" alt="image info" /></p>

<p>We will add a code-behind file for this razor page to keep the code and presentation separate. This will allow easy maintenance for the application.  Right-click on the <span style="color:yellow;background-color:black;">BlazorComputerVision/Pages</span> folder and then select Add » Class. Name the class as <span style="color:yellow;background-color:black;">OCR.razor.cs</span>. The Blazor framework is smart enough to tag this class file to the razor file. Refer to the image shown below.</p>

<p><img src="/img/azure/10/OCRStuct.png" alt="image info" /></p>

<p>Open the Translator.razor file and add the following code at the top.</p>

<pre><code class="language-code">
    @page "/translator"
    @using BlazorTranslator.Models
    @using BlazorTranslator.Data
    @inject TranslationService translationService

</code></pre>

<p>We have defined the route for this component. We are also injecting the <span style="color:yellow;background-color:black;">TranslationService</span> in this component.</p>

<p>Now we will add the following HTML code in this file.</p>

<pre><code class="language-code">
    &lt;h3&gt;Multilanguage translator using Microsoft Translator API Cognitive Service&lt;/h3&gt;
&lt;hr /&gt;
&lt;div class="container"&gt;
    &lt;div class="row"&gt;
        &lt;div class="col-md-6"&gt;
            &lt;select class="form-control" @bind="inputLanguage"&gt;
                &lt;option value=""&gt;-- Select input language --&lt;/option&gt;
                @foreach (KeyValuePair&lt;string, LanguageDetails&gt; lang in LanguageList)
                {
                    &lt;option value="@lang.Key"&gt;@lang.Value.Name&lt;/option&gt;
                }
            &lt;/select&gt;
            &lt;textarea placeholder="Enter text to translate" class="form-control translation-box" rows="5" @bind="@inputText"&gt;&lt;/textarea&gt;
        &lt;/div&gt;
        &lt;div class="col-md-6"&gt;
            &lt;select class="form-control" @onchange="SelectLanguage"&gt;
                &lt;option value=""&gt;-- Select target language --&lt;/option&gt;
                @foreach (KeyValuePair&lt;string, LanguageDetails&gt; lang in LanguageList)
                {
                    &lt;option value="@lang.Key"&gt;@lang.Value.Name&lt;/option&gt;
                }
            &lt;/select&gt;
            &lt;textarea disabled class="form-control translation-box" rows="5"&gt;@outputText&lt;/textarea&gt;
        &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="text-center"&gt;
        &lt;button class="btn btn-primary btn-lg" @onclick="Translate"&gt;Translate&lt;/button&gt;
    &lt;/div&gt;
&lt;/div&gt;
</code></pre>
<p>We have defined two dropdown lists one each for input language and the target language. The Azure Translate Text API will detect the input language and we will use that value to populate the dropdown for input language. We have also defined two text areas for the input and the translated text.</p>

<p>Finally, add the following code in the <span style="color:yellow;background-color:black;">@code </span> section of the page.</p>

<pre><code class="language-code">    @code {
        private TranslationResult[] translations;
        private AvailableLanguage availableLanguages;
        private string outputLanguage { get; set; }
        private string inputLanguage { get; set; }
        string inputText { get; set; }
        string outputText { get; set; }
        private Dictionary&lt;string, LanguageDetails&gt;
        LanguageList = new Dictionary&lt;string, LanguageDetails&gt;();

        protected override async Task OnInitializedAsync()
        {
            availableLanguages = await translationService.GetAvailableLanguages();
            LanguageList = availableLanguages.Translation;
        }
        private void SelectLanguage(ChangeEventArgs langEvent)
        {
            this.outputLanguage = langEvent.Value.ToString();
        }
        private async Task Translate()
        {
            if (!string.IsNullOrEmpty(outputLanguage))
            {
                translations = await translationService.GetTranslatation(this.inputText, this.outputLanguage);
                outputText = translations[0].Translations[0].Text;
                inputLanguage = translations[0].DetectedLanguage.Language;
            }
        }
    }
</code></pre>

<p>We are invoking the <span style="color:yellow;background-color:black;">GetAvailableLanguages</span> method from our service inside the <span style="color:yellow;background-color:black;">OnInitializedAsync</span>. This <span style="color:yellow;background-color:black;">OnInitializedAsync</span> is a lifecycle method that will be invoked upon component initialization. This will make sure that the language dropdown will be populated as the page loads.</p>

<p>The <span style="color:yellow;background-color:black;">SelectLanguage</span> method will be set the <span style="color:yellow;background-color:black;">outputLanguage</span> for the translation. The Translate method will invoke the <span style="color:yellow;background-color:black;">GetTranslatation</span> method from the service. We will set the <span style="color:yellow;background-color:black;">outputText</span> and the language detected for the <span style="color:yellow;background-color:black;">inputLanguage</span> as returned from the service.</p>

<h2 id="add-styling-for-the-translator-component">Add styling for the Translator component</h2>
<p>Navigate to BlazorTranslator\wwwroot\css\site.css file and put the following style definition inside it.</p>

<pre><code class="language-code">
    .translation-box {
        margin: 15px 0px;
    }
</code></pre>

<h2 id="adding-link-to-navigation-menu">Adding Link to Navigation menu</h2>
<p>The last step is to add the link of our Translator component in the navigation menu. Open BlazorTranslator/Shared/NavMenu.razor file and add the following code into it.</p>

<pre><code class="language-code">
    &lt;li class="nav-item px-3"&gt;
    &lt;NavLink class="nav-link" href="translator"&gt;
        &lt;span class="oi oi-list-rich" aria-hidden="true"&gt;&lt;/span&gt; Translator
    &lt;/NavLink&gt;
    &lt;/li&gt;
</code></pre>
<p>Remove the navigation links for Counter and Fetch-data components as they are not required for this application.</p>

<h2 id="execution-demo">Execution Demo</h2>

<p>Press F5 to launch the application. Click on the Translator button on the nav menu in the left. You can perform the multilanguage translation as shown in the image below.</p>

<p><img src="/img/azure/11/output.gif" alt="image info" /></p>

<h2 id="summary">Summary</h2>

<p>We have created a Translator Text Cognitive Services resource on Azure. We have used the Translator Text API to create a multilanguage translator using Blazor. This translator supports more than 60 languages for translation. We fetched the list of supported languages for translation from the global API endpoint for Translator Text.</p>

<p>Get the Source code from <a href="https://github.com/girishgodage/Blazor-Translator-Azure-Cognitive-Services">GitHub</a> and play around to get a better understanding.</p>]]></content><author><name>Girish Godage</name></author><category term="AzureAI" /><category term="learning" /><summary type="html"><![CDATA[Introduction]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://girishgodage.in/img/azure/11/output.gif" /><media:content medium="image" url="https://girishgodage.in/img/azure/11/output.gif" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Optical Character Reader Using Angular And Azure Computer Vision</title><link href="https://girishgodage.in/blog/ocr-using-angular-AzureComputerVision" rel="alternate" type="text/html" title="Optical Character Reader Using Angular And Azure Computer Vision" /><published>2020-12-17T09:55:00+00:00</published><updated>2020-12-17T09:55:00+00:00</updated><id>https://girishgodage.in/blog/ocr-using-angular-AzureComputerVision</id><content type="html" xml:base="https://girishgodage.in/blog/ocr-using-angular-AzureComputerVision"><![CDATA[<h2 id="introduction">Introduction</h2>

<p>In this article, we will create an optical character recognition (OCR) application using Angular and the Azure Computer Vision Cognitive Service. Computer Vision is an AI service that analyzes content in images. We will use the OCR feature of Computer Vision to detect the printed text in an image. The application will extract the text from the image and detects the language of the text. Currently, the OCR API supports 25 languages.</p>

<h2 id="prerequisites">Prerequisites</h2>

<ul>
  <li>Install the latest LTS version of Node.JS from https://nodejs.org/en/download/</li>
  <li>Install the Angular CLI from https://cli.angular.io/</li>
  <li>An Azure subscription account. You can create a free  Azure account at https://azure.microsoft.com/en-in/free/</li>
  <li>Install the .NET Core 3.1 SDK from https://dotnet.microsoft.com/download/dotnet-core/3.1</li>
  <li>Install the latest version of Visual Studio 2019 from https://visualstudio.microsoft.com/downloads/</li>
</ul>

<blockquote>
  <p>We will use an <span style="color:yellow;background-color:black;">ASP.NET Core backend </span> for this application. The <span style="color:yellow;background-color:black;"> ASP.NET Core backend </span> provides a straight forward authentication process to access Azure cognitive services. This will also ensure that the end-user won’t have direct access to cognitive services.</p>
</blockquote>

<h2 id="create-the-azure-computer-vision-cognitive-service-resource">Create the Azure Computer Vision Cognitive Service resource</h2>

<p>Log in to the Azure portal and search for the cognitive services in the search bar and click on the result. Refer to the image shown below.</p>

<p><img src="/img/azure/9/SearchCognitive.png" alt="image info" /></p>

<p>On the next screen, click on the Add button. It will open the cognitive services marketplace page. Search for the Computer Vision in the search bar and click on the search result. It will open the Computer Vision API page. Click on the Create button to create a new Computer Vision resource. Refer to the image shown below.</p>

<p><img src="/img/azure/9/CreateComputerVision.png" alt="image info" /></p>

<p>On the Create page, fill in the details as indicated below.</p>

<ul>
  <li><strong>Name</strong>: Give a unique name for your resource.</li>
  <li><strong>Subscription</strong>: Select the subscription type from the dropdown.</li>
  <li><strong>Pricing tier</strong>: Select the pricing tier as per your choice.</li>
  <li><strong>Resource group</strong>: Select an existing resource group or create a new one.</li>
</ul>

<p>Click on the Create button. Refer to the image shown below.</p>

<p><img src="/img/azure/9/CreateComputerVision_1.png" alt="image info" /></p>

<p><img src="/img/azure/9/CreateComputerVision_2.png" alt="image info" /></p>

<p>After your resource is successfully deployed, click on the “Go to resource” button. You can see the Key and the endpoint for the newly created Computer Vision resource. Refer to the image shown below.</p>

<p><img src="/img/azure/9/ComputerVisionKeyNEndPoint.png" alt="image info" /></p>

<p>Make a note of the <strong>key and the endpoint</strong>. We will be using these in the latter part of this article to invoke the Computer Vision OCR API from the .NET Code. The values are masked here for privacy.</p>

<h2 id="creating-the-aspnet-core-application">Creating the ASP.NET Core application</h2>

<p>Open Visual Studio 2019 and click on “Create a new Project”. A “Create a new Project” dialog will open. Select “ASP.NET Core Web Application” and click on Next. Now you will be at “Configure your new project” screen, provide the name for your application as ngComputerVision and click on create. Refer to the image shown below.</p>

<p><img src="/img/azure/9/Configure_CoreWebApp.png" alt="image info" /></p>

<p>You will be navigated to “Create a new ASP.NET Core web application” screen. Select “.NET Core” and “ASP.NET Core 3.1” from the dropdowns on the top. Then, select the “Angular” project template and click on Create. Refer to the image shown below.</p>

<p><img src="/img/azure/9/Create_CoreWebApp.png" alt="image info" /></p>

<p>This will create our project. The folder structure of the application is shown below.</p>

<p><img src="/img/azure/9/SolutionFolderStructure.png" alt="image info" /></p>

<p>The <span style="color:yellow;background-color:black;">ClientApp </span> folder contains the Angular code for our application. The Controllers folders will contain our API controllers. The angular components are present inside the <span style="color:yellow;background-color:black;">ClientApp\src\app </span> folder. The default template contains few Angular components. These components won’t affect our application, but for the sake of simplicity, we will delete fetchdata and counter folders from <span style="color:yellow;background-color:black;">ClientApp/app/components</span> folder. Also, remove the reference for these two components from the <span style="color:yellow;background-color:black;">app.module.ts</span> file.</p>

<h2 id="installing-computer-vision-api-library">Installing Computer Vision API library</h2>
<p>We will install the Azure Computer Vision API library which will provide us with the models out of the box to handle the Computer Vision REST API response. To install the package, navigate to Tools » NuGet Package Manager » Package Manager Console. It will open the Package Manager Console. Run the command as shown below.</p>

<pre><code class="language-code">  Install-Package Microsoft.Azure.CognitiveServices.Vision.ComputerVision -Version 5.0.0

</code></pre>
<p>You can learn more about this package at the <a href="https://www.nuget.org/packages/Microsoft.Azure.CognitiveServices.Vision.ComputerVision/">NuGet gallery</a>.</p>

<h2 id="create-the-models">Create the Models</h2>

<p>Right-click on the <span style="color:yellow;background-color:black;">ngComputerVision</span> project and select Add » New Folder. Name the folder as Models. Again, right-click on the Models folder and select Add » Class to add a new class file. Put the name of your class as <span style="color:yellow;background-color:black;">LanguageDetails.cs</span> and click Add.</p>

<p>Open <span style="color:yellow;background-color:black;">LanguageDetails.cs</span> and put the following code inside it.</p>

<pre><code class="language-code">  namespace ngComputerVision.Models
{
    public class LanguageDetails
    {
        public string Name { get; set; }
        public string NativeName { get; set; }
        public string Dir { get; set; }
    }
}

</code></pre>

<p>Similarly, add a new class file <span style="color:yellow;background-color:black;">AvailableLanguage.cs </span> and put the following code inside it.</p>

<pre><code class="language-code">  using System.Collections.Generic;
  namespace ngComputerVision.Models
  {
      public class AvailableLanguage
      {
          public Dictionary&lt;string, LanguageDetails&gt; Translation { get; set; }
      }
  }

</code></pre>
<p>We will also add two classes as DTO (Data Transfer Object) for sending data back to the client.</p>

<p>Create a new folder and name it <span style="color:yellow;background-color:black;">DTOModels</span>. Add the new class file <span style="color:yellow;background-color:black;">AvailableLanguageDTO.cs</span> in the <span style="color:yellow;background-color:black;">DTOModels</span> folder and put the following code inside it.</p>

<pre><code class="language-code">
  namespace ngComputerVision.DTOModels
  {
      public class AvailableLanguageDTO
      {
          public string LanguageID { get; set; }
          public string LanguageName { get; set; }
      }
  }

</code></pre>

<p>Add the <span style="color:yellow;background-color:black;">OcrResultDTO.cs</span> file and put the following code inside it.</p>

<pre><code class="language-code">  namespace ngComputerVision.DTOModels
  {
      public class OcrResultDTO
      {
          public string Language { get; set; }
          public string DetectedText { get; set; }
      }
  }

</code></pre>
<h2 id="adding-the-ocr-controller">Adding the OCR Controller</h2>

<p>We will add a new controller to our application. Right-click on the Controllers folder and select Add » New Item. An “Add New Item” dialog box will open. Select “Visual C#” from the left panel, then select “API Controller Class” from templates panel and put the name as <span style="color:yellow;background-color:black;">OCRController.cs</span>. Click on Add. Refer to the image below.</p>

<p><img src="/img/azure/9/AddAPIController.png" alt="image info" /></p>

<p>The OCRController will handle the image recognition requests from the client app. This controller will also return the list of all the languages supported by OCR API.</p>

<p>Open the <span style="color:yellow;background-color:black;">OCRController.cs</span> file and put the following code inside it.</p>

<pre><code class="language-code">  using System;
  using System.Threading.Tasks;
  using Microsoft.AspNetCore.Mvc;
  using System.Net.Http;
  using System.Net.Http.Headers;
  using Newtonsoft.Json.Linq;
  using System.IO;
  using Newtonsoft.Json;
  using System.Text;
  using ngComputerVision.Models;
  using System.Collections.Generic;
  using Microsoft.Azure.CognitiveServices.Vision.ComputerVision.Models;
  using ngComputerVision.DTOModels;
  namespace ngComputerVision.Controllers
  {
      [Produces("application/json")]
      [Route("api/[controller]")]
      public class OCRController : Controller
      {
          static string subscriptionKey;
          static string endpoint;
          static string uriBase;
          public OCRController()
          {
              subscriptionKey = "fc791774e60e455da79546c50e1ca504";
              endpoint = "https://ngocrdemo.cognitiveservices.azure.com/";
              uriBase = endpoint + "vision/v2.1/ocr";
          }
          [HttpPost, DisableRequestSizeLimit]
          public async Task&lt;OcrResultDTO&gt; Post()
          {
              StringBuilder sb = new StringBuilder();
              OcrResultDTO ocrResultDTO = new OcrResultDTO();
              try
              {
                  if (Request.Form.Files.Count &gt; 0)
                  {
                      var file = Request.Form.Files[Request.Form.Files.Count - 1];
                      if (file.Length &gt; 0)
                      {
                          var memoryStream = new MemoryStream();
                          file.CopyTo(memoryStream);
                          byte[] imageFileBytes = memoryStream.ToArray();
                          memoryStream.Flush();
                          string JSONResult = await ReadTextFromStream(imageFileBytes);
                          OcrResult ocrResult = JsonConvert.DeserializeObject&lt;OcrResult&gt;(JSONResult);
                          if (!ocrResult.Language.Equals("unk"))
                          {
                              foreach (OcrLine ocrLine in ocrResult.Regions[0].Lines)
                              {
                                  foreach (OcrWord ocrWord in ocrLine.Words)
                                  {
                                      sb.Append(ocrWord.Text);
                                      sb.Append(' ');
                                  }
                                  sb.AppendLine();
                              }
                          }
                          else
                          {
                              sb.Append("This language is not supported.");
                          }
                          ocrResultDTO.DetectedText = sb.ToString();
                          ocrResultDTO.Language = ocrResult.Language;
                      }
                  }
                  return ocrResultDTO;
              }
              catch
              {
                  ocrResultDTO.DetectedText = "Error occurred. Try again";
                  ocrResultDTO.Language = "unk";
                  return ocrResultDTO;
              }
          }
          static async Task&lt;string&gt; ReadTextFromStream(byte[] byteData)
          {
              try
              {
                  HttpClient client = new HttpClient();
                  client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", subscriptionKey);
                  string requestParameters = "language=unk&amp;detectOrientation=true";
                  string uri = uriBase + "?" + requestParameters;
                  HttpResponseMessage response;
                  using (ByteArrayContent content = new ByteArrayContent(byteData))
                  {
                      content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
                      response = await client.PostAsync(uri, content);
                  }
                  string contentString = await response.Content.ReadAsStringAsync();
                  string result = JToken.Parse(contentString).ToString();
                  return result;
              }
              catch (Exception e)
              {
                  return e.Message;
              }
          }
          [HttpGet]
          public async Task&lt;List&lt;AvailableLanguageDTO&gt;&gt; GetAvailableLanguages()
          {
              string endpoint = "https://api.cognitive.microsofttranslator.com/languages?api-version=3.0&amp;scope=translation";
              var client = new HttpClient();
              using (var request = new HttpRequestMessage())
              {
                  request.Method = HttpMethod.Get;
                  request.RequestUri = new Uri(endpoint);
                  var response = await client.SendAsync(request).ConfigureAwait(false);
                  string result = await response.Content.ReadAsStringAsync();
                  AvailableLanguage deserializedOutput = JsonConvert.DeserializeObject&lt;AvailableLanguage&gt;(result);
                  List&lt;AvailableLanguageDTO&gt; availableLanguage = new List&lt;AvailableLanguageDTO&gt;();
                  foreach (KeyValuePair&lt;string, LanguageDetails&gt; translation in deserializedOutput.Translation)
                  {
                      AvailableLanguageDTO language = new AvailableLanguageDTO();
                      language.LanguageID = translation.Key;
                      language.LanguageName = translation.Value.Name;
                      availableLanguage.Add(language);
                  }
                  return availableLanguage;
              }
          }
      }
  } 

</code></pre>

<p>In the constructor of the class, we have initialized the key and the endpoint URL for the OCR API.</p>

<p>The Post method will receive the image data as a file collection in the request body and return an object of type <span style="color:yellow;background-color:black;">OcrResultDTO</span>. We will convert the image data to a byte array and invoke the <span style="color:yellow;background-color:black;">ReadTextFromStream</span> method. We will deserialize the response into an object of type <span style="color:yellow;background-color:black;">OcrResult</span>. We will then form the sentence by iterating over the <span style="color:yellow;background-color:black;">OcrWord</span> object.</p>

<p>Inside the <span style="color:yellow;background-color:black;">ReadTextFromStream</span> method, we will create a new <span style="color:yellow;background-color:black;">HttpRequestMessage</span>. This HTTP request is a Post request. We will pass the subscription key in the header of the request. The OCR API will return a JSON object having each word from the image as well as the detected language of the text.</p>

<p>The <span style="color:yellow;background-color:black;">GetAvailableLanguages</span> method will return the list of all the language supported by the Translate Text API. We will set the request URI and create a <span style="color:yellow;background-color:black;">HttpRequestMessage</span> which will be a Get request. This request URI will return a JSON object which will be deserialized to an object of type <span style="color:yellow;background-color:black;">AvailableLanguage</span>.</p>

<h2 id="why-do-we-need-to-fetch-the-list-of-supported-languages">Why do we need to fetch the list of supported languages?</h2>

<p>The OCR API returns the language code (e.g. en for English, de for German, etc.) of the detected language. But we cannot display the language code on the UI as it is not user-friendly. Therefore, we need a dictionary to look up the language name corresponding to the language code.</p>

<p>The Azure Computer Vision OCR API supports 25 languages. To know all the languages supported by OCR API see the list of <a href="https://docs.microsoft.com/en-us/azure/cognitive-services/computer-vision/language-support">supported languages</a>. These languages are a subset of the languages supported by the Azure Translate Text API. Since there is no dedicated API endpoint to fetch the list of languages supported by OCR API, therefore, we are using the Translate Text API endpoint to fetch the list of languages. We will create the language lookup dictionary using the JSON response from this API call and filter the result based on the language code returned by the OCR API.</p>

<h2 id="working-on-the-client-side-of-the-application">Working on the Client side of the application</h2>

<p>The code for the client-side is available in the <span style="color:yellow;background-color:black;">ClientApp</span> folder. We will use Angular CLI to work with the client code.</p>

<blockquote>
  <p>Using Angular CLI is not mandatory. I am using Angular CLI here as it is user-friendly and easy to use. If you don’t want to use CLI then you can create the files for components and services manually.</p>
</blockquote>

<p>Navigate to the <span style="color:yellow;background-color:black;">ngComputerVision\ClientApp </span> folder in your machine and open a command window. We will execute all our Angular CLI commands in this window.</p>

<h2 id="create-the-models-1">Create the models</h2>

<p>Create a folder called <span style="color:yellow;background-color:black;">models</span> inside the <span style="color:yellow;background-color:black;">ClientApp\src\app</span> folder. Now we will create a file <span style="color:yellow;background-color:black;">availablelanguage.ts</span> in the models folder. Put the following code in it.</p>

<pre><code class="language-code">  export class AvailableLanguage {
    languageID: string;
    languageName: string;
  }

</code></pre>

<p>Similarly, create another file inside the models folder called <span style="color:yellow;background-color:black;">ocrresult.ts</span>. Put the following code in it.</p>

<pre><code class="language-code">  export class OcrResult {
    language: string;
    detectedText: string
  }

</code></pre>

<p>You can observe that both these classes have the same definition as the DTO classes we created on the server-side. This will allow us to bind the data returned from the server directly to our models.</p>

<h2 id="create-the-computer-vision-service">Create the Computer Vision Service</h2>

<p>We will create an Angular service which will invoke the Web API endpoints, convert the Web API response to JSON and pass it to our component. Run the following command.</p>

<pre><code class="language-code">
  ng g s services\Computervision

</code></pre>

<p>This command will create a folder name as services and then create the following two files inside it.</p>

<ul>
  <li><strong>computervision.service.ts</strong> — the service class file.</li>
  <li><strong>computervision.service.spec.ts</strong> — the unit test file for service.</li>
</ul>

<p>Open <span style="color:yellow;background-color:black;">computervision.service.ts</span> file and put the following code inside it.</p>

<pre><code class="language-code">  import { Injectable } from '@angular/core';
  import { HttpClient } from '@angular/common/http';
  @Injectable({
    providedIn: 'root'
  })
  export class ComputervisionService {
    baseURL: string;
    constructor(private http: HttpClient) {
      this.baseURL = '/api/OCR';
    }
    getAvailableLanguage() {
      return this.http.get(this.baseURL)
        .pipe(response =&gt; {
          return response;
        });
    }
    getTextFromImage(image: FormData) {
      return this.http.post(this.baseURL, image)
        .pipe(response =&gt; {
          return response;
        });
    }
  }

</code></pre>
<p>We have defined a variable baseURL which will hold the endpoint URL of our API. We will initialize the baseURL in the constructor and set it to the endpoint of the <span style="color:yellow;background-color:black;">OCRController</span>.</p>

<p>The <span style="color:yellow;background-color:black;">getAvailableLanguage</span> method will send a Get request to the <span style="color:yellow;background-color:black;">GetAvailableLanguages</span> method of the <span style="color:yellow;background-color:black;">OCRController</span> to fetch the list of supported languages for OCR.</p>

<p>The <span style="color:yellow;background-color:black;">getTextFromImage</span> method will send a Post request to the <span style="color:yellow;background-color:black;">OCRController</span> and supply the parameter of type <span style="color:yellow;background-color:black;">FormData</span>. It will fetch the detected text from the image and language code of the text.</p>

<h2 id="create-the-ocr-component">Create the Ocr component</h2>

<p>Run the following command in the command prompt to create the <span style="color:yellow;background-color:black;">OcrComponent</span>.</p>

<pre><code class="language-code">  
  ng g c ocr --module app

</code></pre>

<p>The –module flag will ensure that this component will get registered at <span style="color:yellow;background-color:black;">app.module.ts</span>.</p>

<p>Open <span style="color:yellow;background-color:black;">ocr.component.html</span> and put the following code in it.</p>

<pre><code class="language-code">    &lt;h2&gt;Optical Character Recognition (OCR) using Angular and Azure Computer Vision Cognitive Services&lt;/h2&gt;
  &lt;div class="row"&gt;
    &lt;div class="col-md-5"&gt;
      &lt;textarea disabled class="form-control" rows="10" cols="15"&gt;&lt;/textarea&gt;
      &lt;hr /&gt;
      &lt;div class="row"&gt;
        &lt;div class="col-sm-5"&gt;
          &lt;label&gt;&lt;strong&gt; Detected Language :&lt;/strong&gt;&lt;/label&gt;
        &lt;/div&gt;
        &lt;div class="col-sm-6"&gt;
          &lt;input disabled type="text" class="form-control" value= /&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="col-md-5"&gt;
      &lt;div class="image-container"&gt;
        &lt;img class="preview-image" src=&gt;
      &lt;/div&gt;
      &lt;input type="file" (change)="uploadImage($event)" /&gt;
      &lt;p&gt;&lt;/p&gt;
      &lt;hr /&gt;
      &lt;button [disabled]="loading" class="btn btn-primary btn-lg" (click)="GetText()"&gt;
        &lt;span *ngIf="loading" class="spinner-border spinner-border-sm mr-1"&gt;&lt;/span&gt;Extract Text
      &lt;/button&gt;
    &lt;/div&gt;
  &lt;/div&gt;
</code></pre>

<p>We have defined a text area to display the detected text and a text box for displaying the detected language. We have defined a file upload control which will allow us to upload an image. After uploading the image, the preview of the image will be displayed using an <span style="color:yellow;background-color:black;">img</span> element.</p>

<p>Open <span style="color:yellow;background-color:black;">ocr.component.ts</span> and put the following code in it.</p>

<pre><code class="language-code">  import { Component, OnInit } from '@angular/core';
import { ComputervisionService } from '../services/computervision.service';
import { AvailableLanguage } from '../models/availablelanguage';
import { OcrResult } from '../models/ocrresult';
@Component({
  selector: 'app-ocr',
  templateUrl: './ocr.component.html',
  styleUrls: ['./ocr.component.css']
})
export class OcrComponent implements OnInit {
  loading = false;
  imageFile;
  imagePreview;
  imageData = new FormData();
  availableLanguage: AvailableLanguage[];
  DetectedTextLanguage: string;
  ocrResult: OcrResult;
  DefaultStatus: string;
  status: string;
  maxFileSize: number;
  isValidFile = true;
  constructor(private computervisionService: ComputervisionService) {
    this.DefaultStatus = "Maximum size allowed for the image is 4 MB";
    this.status = this.DefaultStatus;
    this.maxFileSize = 4 * 1024 * 1024; // 4MB
  }
  ngOnInit() {
    this.computervisionService.getAvailableLanguage().subscribe(
      (result: AvailableLanguage[]) =&gt; this.availableLanguage = result
    );
  }
  uploadImage(event) {
    this.imageFile = event.target.files[0];
    if (this.imageFile.size &gt; this.maxFileSize) {
      this.status = `The file size is ${this.imageFile.size} bytes, this is more than the allowed limit of ${this.maxFileSize} bytes.`;
      this.isValidFile = false;
    } else if (this.imageFile.type.indexOf('image') == -1) {
      this.status = "Please upload a valid image file";
      this.isValidFile = false;
    } else {
      const reader = new FileReader();
      reader.readAsDataURL(event.target.files[0]);
      reader.onload = () =&gt; {
        this.imagePreview = reader.result;
      };
      this.status = this.DefaultStatus;
      this.isValidFile = true;
    }
  }
  GetText() {
    if (this.isValidFile) {
      this.loading = true;
      this.imageData.append('imageFile', this.imageFile);
      this.computervisionService.getTextFromImage(this.imageData).subscribe(
        (result: OcrResult) =&gt; {
          this.ocrResult = result;
          if (this.availableLanguage.find(x =&gt; x.languageID === this.ocrResult.language)) {
            this.DetectedTextLanguage = this.availableLanguage.find(x =&gt; x.languageID === this.ocrResult.language).languageName;
          } else {
            this.DetectedTextLanguage = "unknown";
          }
          this.loading = false;
        });
    }
  }
}
</code></pre>

<p>We will inject the <span style="color:yellow;background-color:black;">ComputervisionService</span> in the constructor of the <span style="color:yellow;background-color:black;">OcrComponent</span> and set a message and the value for the max image size allowed inside the constructor.</p>

<p>We will invoke the <span style="color:yellow;background-color:black;">getAvailableLanguage</span> method of our service in the <span style="color:yellow;background-color:black;">ngOnInit</span> and store the result in an array of type <span style="color:yellow;background-color:black;">AvailableLanguage<span>.</span></span></p>

<p>The <span style="color:yellow;background-color:black;">uploadImage</span> method will be invoked upon uploading an image. We will check if the uploaded file is a valid image and within the allowed size limit. We will process the image data using a <span style="color:yellow;background-color:black;">FileReader</span> object. The <span style="color:yellow;background-color:black;">readAsDataURL</span> method will read the contents of the uploaded file. Upon successful completion of the read operation, the <span style="color:yellow;background-color:black;">reader.onload</span> event will be triggered. The value of <span style="color:yellow;background-color:black;">imagePreview</span> will be set to the result returned by the fileReader object, which is of type <span style="color:yellow;background-color:black;">ArrayBuffer</span>.</p>

<p>Inside the <span style="color:yellow;background-color:black;">GetText</span> method, we will append the image file to a variable for type <span style="color:yellow;background-color:black;">FormData</span>. We will invoke the <span style="color:yellow;background-color:black;">getTextFromImage</span> of the service and bind the result to an object of type <span style="color:yellow;background-color:black;">OcrResult</span>. We will search for the language name from the array <span style="color:yellow;background-color:black;">availableLanguage</span>, based on the language code returned from the service. If the language code is not found, we will set the language as unknown.</p>

<p>We will add the styling for the text area in <span style="color:yellow;background-color:black;">ocr.component.css</span> as shown below.</p>

<pre><code class="language-code">
  .preview-image {
      max-height: 300px;
      max-width: 300px;
  }
  .image-container{
    display: flex;
    padding: 15px;
    align-content: center;
    align-items: center;
    justify-content: center;
    border: 2px dashed skyblue;
  }

</code></pre>

<h2 id="adding-the-links-in-nav-menu">Adding the links in Nav Menu</h2>

<p>We will add the navigation links for our components in the nav menu. Open <span style="color:yellow;background-color:black;">nav-menu.component.html</span> and remove the links for Counter and Fetch data components. Add the following lines in the list of navigation links.</p>

<pre><code class="language-code">  &lt;li class="nav-item" [routerLinkActive]="['link-active']"&gt;
    &lt;a class="nav-link text-dark" routerLink='/computer-vision-ocr'&gt;Computer Vision&lt;/a&gt;
  &lt;/li&gt;
</code></pre>

<h2 id="execution-demo">Execution Demo</h2>

<p>Press F5 to launch the application. Click on the Computer Vision button on the nav menu at the top. You can upload an image and extract the text from the image as shown in the image below.</p>

<p><img src="/img/azure/9/output.gif" alt="image info" /></p>

<h2 id="summary">Summary</h2>

<p>We have created an optical character recognition (OCR) application using Angular and the Computer Vision Azure Cognitive Service. The application is able to extract the printed text from the uploaded image and recognizes the language of the text. The OCR API of the Computer Vision is used which can recognize text in 25 languages.</p>

<p>Get the Source code from <a href="https://github.com/girishgodage/AngularComputerVisionAzureCognitiveServices">GitHub</a> and play around to get a better understanding.</p>]]></content><author><name>Girish Godage</name></author><category term="AzureAI" /><category term="learning" /><summary type="html"><![CDATA[Introduction]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://girishgodage.in/img/azure/9/output.gif" /><media:content medium="image" url="https://girishgodage.in/img/azure/9/output.gif" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Optical Character Reader Using Blazor And Azure Computer Vision</title><link href="https://girishgodage.in/blog/ocr-using-blazor-AzureComputerVision" rel="alternate" type="text/html" title="Optical Character Reader Using Blazor And Azure Computer Vision" /><published>2020-12-17T09:55:00+00:00</published><updated>2020-12-17T09:55:00+00:00</updated><id>https://girishgodage.in/blog/ocr-using-blazor-AzureComputerVision</id><content type="html" xml:base="https://girishgodage.in/blog/ocr-using-blazor-AzureComputerVision"><![CDATA[<h2 id="introduction">Introduction</h2>

<p>In this article, we will create an optical character recognition (OCR) application using Blazor and the Azure Computer Vision Cognitive Service. Computer Vision is an AI service that analyzes content in images. We will use the OCR feature of Computer Vision to detect the printed text in an image. The application will extract the text from the image and detects the language of the text. Currently, the OCR API supports 25 languages.</p>

<p><img src="/img/azure/10/output.gif" alt="image info" /></p>

<h2 id="prerequisites">Prerequisites</h2>
<ul>
  <li>Install the latest .NET Core 3.1 SDK from https://dotnet.microsoft.com/download/dotnet-core/3.1</li>
  <li>Install the latest version of Visual Studio 2019 from https://visualstudio.microsoft.com/downloads/</li>
  <li>An Azure subscription account. You can create a free Azure account  at https://azure.microsoft.com/en-in/free/</li>
</ul>

<h2 id="image-requirements">Image requirements</h2>

<p>The OCR API will work on images that meet the requirements as mentioned below:</p>

<ul>
  <li>The format of the image must be JPEG, PNG, GIF, or BMP.</li>
  <li>The size of the image must be between 50 x 50 and 4200 x 4200 pixels.</li>
  <li>The image file size should be less than 4 MB.</li>
  <li>The text in the image can be rotated by any multiple of 90 degrees plus a small angle of up to 40 degrees.</li>
</ul>

<h2 id="create-the-azure-computer-vision-cognitive-service-resource">Create the Azure Computer Vision Cognitive Service resource</h2>

<p>Log in to the Azure portal and search for the cognitive services in the search bar and click on the result. Refer to the image shown below.</p>

<p><img src="/img/azure/9/SearchCognitive.png" alt="image info" /></p>

<p>On the next screen, click on the Add button. It will open the cognitive services marketplace page. Search for the Computer Vision in the search bar and click on the search result. It will open the Computer Vision API page. Click on the Create button to create a new Computer Vision resource. Refer to the image shown below.</p>

<p><img src="/img/azure/9/CreateComputerVision.png" alt="image info" /></p>

<p>On the Create page, fill in the details as indicated below.</p>

<ul>
  <li><strong>Name</strong>: Give a unique name for your resource.</li>
  <li><strong>Subscription</strong>: Select the subscription type from the dropdown.</li>
  <li><strong>Pricing tier</strong>: Select the pricing tier as per your choice.</li>
  <li><strong>Resource group</strong>: Select an existing resource group or create a new one.</li>
</ul>

<p>Click on the Create button. Refer to the image shown below.</p>

<p><img src="/img/azure/10/CreateComputerVision.png" alt="image info" /></p>

<p><img src="/img/azure/10/CreateComputerVision_1.png" alt="image info" /></p>

<p>After your resource is successfully deployed, click on the “Go to resource” button. You can see the Key and the endpoint for the newly created Computer Vision resource. Refer to the image shown below.</p>

<p><img src="/img/azure/10/ComputerVisionKeyNEndPoint.png" alt="image info" /></p>

<p>Make a note of the <strong>key and the endpoint</strong>. We will be using these in the latter part of this article to invoke the Computer Vision OCR API from the .NET Code. The values are masked here for privacy.</p>

<h2 id="create-a-server-side-blazor-application">Create a Server-Side Blazor Application</h2>

<p>Open Visual Studio 2019, click on “Create a new project”. Select “Blazor App” and click on the “Next” button. Refer to the image shown below.</p>

<p><img src="/img/azure/10/Create_BlazorApp.png" alt="image info" /></p>

<p>On the next window, put the project name as <span style="color:yellow;background-color:black;">BlazorComputerVision</span> and click on the “Create” button. The next window will ask you to select the type of Blazor app. Select <span style="color:yellow;background-color:black;">Blazor Server App </span> and click on the Create button to create a new server-side Blazor application. Refer to the image shown below.</p>

<p><img src="/img/azure/10/Create_BlazorApp_1.png" alt="image info" /></p>

<h2 id="installing-computer-vision-api-library">Installing Computer Vision API library</h2>
<p>We will install the Azure Computer Vision API library which will provide us with the models out of the box to handle the Computer Vision REST API response. To install the package, navigate to Tools » NuGet Package Manager » Package Manager Console. It will open the Package Manager Console. Run the command as shown below.</p>

<pre><code class="language-code">  Install-Package Microsoft.Azure.CognitiveServices.Vision.ComputerVision -Version 5.0.0

</code></pre>
<p>You can learn more about this package at the <a href="https://www.nuget.org/packages/Microsoft.Azure.CognitiveServices.Vision.ComputerVision/">NuGet gallery</a>.</p>

<h2 id="create-the-models">Create the Models</h2>

<p>Right-click on the <span style="color:yellow;background-color:black;">BlazorComputerVision</span> project and select Add » New Folder. Name the folder as Models. Again, right-click on the Models folder and select Add » Class to add a new class file. Put the name of your class as <span style="color:yellow;background-color:black;">LanguageDetails.cs</span> and click Add.</p>

<p>Open <span style="color:yellow;background-color:black;">LanguageDetails.cs</span> and put the following code inside it.</p>

<pre><code class="language-code">  namespace BlazorComputerVision.Models
  {
      public class LanguageDetails
      {
          public string Name { get; set; }
          public string NativeName { get; set; }
          public string Dir { get; set; }
      }
  }

</code></pre>

<p>Similarly, add a new class file <span style="color:yellow;background-color:black;">AvailableLanguage.cs </span> and put the following code inside it.</p>

<pre><code class="language-code"> using System.Collections.Generic;
  namespace BlazorComputerVision.Models
  {
      public class AvailableLanguage
      {
          public Dictionary&lt;string, LanguageDetails&gt; Translation { get; set; }
      }
  }

</code></pre>
<p>Finally, we will add a class as DTO (Data Transfer Object) for sending data back to the client.Add the new class file <span style="color:yellow;background-color:black;">OcrResultDTO.cs</span> in the <span style="color:yellow;background-color:black;">Models</span> folder and put the following code inside it.</p>

<pre><code class="language-code">
  namespace BlazorComputerVision.Models
  {
      public class OcrResultDTO
      {
          public string Language { get; set; }
          public string DetectedText { get; set; }
      }
  }

</code></pre>

<h2 id="create-the-computer-vision-service">Create the Computer Vision Service</h2>

<p>Right-click on the <span style="color:yellow;background-color:black;">BlazorComputerVision/Data</span> folder and select Add » Class to add a new class file. Put the name of the file as <span style="color:yellow;background-color:black;">ComputerVisionService.cs</span> and click on Add.</p>

<p>Open the <span style="color:yellow;background-color:black;">ComputerVisionService.cs</span> file and put the following code inside it.</p>

<pre><code class="language-code">  using BlazorComputerVision.Models;
  using Microsoft.Azure.CognitiveServices.Vision.ComputerVision.Models;
  using Newtonsoft.Json;
  using Newtonsoft.Json.Linq;
  using System;
  using System.Net.Http;
  using System.Net.Http.Headers;
  using System.Text;
  using System.Threading.Tasks;
  namespace BlazorComputerVision.Data
  {
      public class ComputerVisionService
      {
          static string subscriptionKey;
          static string endpoint;
          static string uriBase;
          public ComputerVisionService()
          {
              subscriptionKey = "88b4cb369bcc4fc7bae5595f45400d45";
              endpoint = "https://girishblazorocrdemo.cognitiveservices.azure.com/";
              uriBase = endpoint + "vision/v2.1/ocr";
          }
          public async Task&lt;OcrResultDTO&gt; GetTextFromImage(byte[] imageFileBytes)
          {
              StringBuilder sb = new StringBuilder();
              OcrResultDTO ocrResultDTO = new OcrResultDTO();
              try
              {
                  string JSONResult = await ReadTextFromStream(imageFileBytes);
                  OcrResult ocrResult = JsonConvert.DeserializeObject&lt;OcrResult&gt;(JSONResult);
                  if (!ocrResult.Language.Equals("unk"))
                  {
                      foreach (OcrLine ocrLine in ocrResult.Regions[0].Lines)
                      {
                          foreach (OcrWord ocrWord in ocrLine.Words)
                          {
                              sb.Append(ocrWord.Text);
                              sb.Append(' ');
                          }
                          sb.AppendLine();
                      }
                  }
                  else
                  {
                      sb.Append("This language is not supported.");
                  }
                  ocrResultDTO.DetectedText = sb.ToString();
                  ocrResultDTO.Language = ocrResult.Language;
                  return ocrResultDTO;
              }
              catch
              {
                  ocrResultDTO.DetectedText = "Error occurred. Try again";
                  ocrResultDTO.Language = "unk";
                  return ocrResultDTO;
              }
          }
          static async Task&lt;string&gt; ReadTextFromStream(byte[] byteData)
          {
              try
              {
                  HttpClient client = new HttpClient();
                  client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", subscriptionKey);
                  string requestParameters = "language=unk&amp;detectOrientation=true";
                  string uri = uriBase + "?" + requestParameters;
                  HttpResponseMessage response;
                  using (ByteArrayContent content = new ByteArrayContent(byteData))
                  {
                      content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
                      response = await client.PostAsync(uri, content);
                  }
                  string contentString = await response.Content.ReadAsStringAsync();
                  string result = JToken.Parse(contentString).ToString();
                  return result;
              }
              catch (Exception e)
              {
                  return e.Message;
              }
          }
          public async Task&lt;AvailableLanguage&gt; GetAvailableLanguages()
          {
              string endpoint = "https://api.cognitive.microsofttranslator.com/languages?api-version=3.0&amp;scope=translation";
              var client = new HttpClient();
              using (var request = new HttpRequestMessage())
              {
                  request.Method = HttpMethod.Get;
                  request.RequestUri = new Uri(endpoint);
                  var response = await client.SendAsync(request).ConfigureAwait(false);
                  string result = await response.Content.ReadAsStringAsync();
                  AvailableLanguage deserializedOutput = JsonConvert.DeserializeObject&lt;AvailableLanguage&gt;(result);
                  return deserializedOutput;
              }
          }
      }
  } 

</code></pre>

<p>In the constructor of the class, we have initialized the key and the endpoint URL for the OCR API.</p>

<p>Inside the <span style="color:yellow;background-color:black;">ReadTextFromStream</span> method, we will create a new <span style="color:yellow;background-color:black;">HttpRequestMessage</span>. This HTTP request is a Post request. We will pass the subscription key in the header of the request. The OCR API will return a JSON object having each word from the image as well as the detected language of the text.</p>

<p>The <span style="color:yellow;background-color:black;">GetTextFromImage</span> method will accept the image data as a byte array and returns an object of type <span style="color:yellow;background-color:black;">OcrResultDTO</span>. We will invoke the <span style="color:yellow;background-color:black;">ReadTextFromStream</span> method and deserialize the response into an object of type <span style="color:yellow;background-color:black;">OcrResult</span>. We will then form the sentence by iterating over the <span style="color:yellow;background-color:black;">OcrWord</span> object.</p>

<p>The <span style="color:yellow;background-color:black;">GetAvailableLanguages</span> method will return the list of all the language supported by the Translate Text API. We will set the request URI and create a <span style="color:yellow;background-color:black;">HttpRequestMessage</span> which will be a Get request. This request URI will return a JSON object which will be deserialized to an object of type <span style="color:yellow;background-color:black;">AvailableLanguage</span>.</p>

<h2 id="why-do-we-need-to-fetch-the-list-of-supported-languages">Why do we need to fetch the list of supported languages?</h2>

<p>The OCR API returns the language code (e.g. en for English, de for German, etc.) of the detected language. But we cannot display the language code on the UI as it is not user-friendly. Therefore, we need a dictionary to look up the language name corresponding to the language code.</p>

<p>The Azure Computer Vision OCR API supports 25 languages. To know all the languages supported by OCR API see the list of <a href="https://docs.microsoft.com/en-us/azure/cognitive-services/computer-vision/language-support">supported languages</a>. These languages are a subset of the languages supported by the Azure Translate Text API. Since there is no dedicated API endpoint to fetch the list of languages supported by OCR API, therefore, we are using the Translate Text API endpoint to fetch the list of languages. We will create the language lookup dictionary using the JSON response from this API call and filter the result based on the language code returned by the OCR API.</p>

<h2 id="install-blazorinputfile-nuget-package">Install BlazorInputFile NuGet package</h2>
<p><span style="color:yellow;background-color:black;">BlazorInputFile</span> is a file input component for Blazor applications. It provides the ability to upload single or multiple files to a Blazor app.</p>

<p>Open <span style="color:yellow;background-color:black;">BlazorComputerVision.csproj</span> file and add a dependency for the BlazorInputFile package as shown below:</p>

<pre><code class="language-code">  &lt;ItemGroup&gt;
    &lt;PackageReference Include="BlazorInputFile" Version="0.2.0" /&gt;
&lt;/ItemGroup&gt;

</code></pre>

<p>Open <span style="color:yellow;background-color:black;">BlazorComputerVision\Pages_Host.cshtml</span> file and add the reference for the package’s JavaScript file by adding the following line in the <span style="color:yellow;background-color:black;">head</span> section.</p>

<pre><code class="language-code">
&lt;script src="_content/BlazorInputFile/inputfile.js"&gt;&lt;/script&gt;

</code></pre>
<p>Add the following line in the _Imports.razor file.</p>

<pre><code class="language-code">  @using BlazorInputFile
</code></pre>

<h2 id="configuring-the-service">Configuring the Service</h2>

<p>To make the service available to the components we need to configure it on the server-side app. Open the <span style="color:yellow;background-color:black;">Startup.cs</span> file. Add the following line inside the <span style="color:yellow;background-color:black;">ConfigureServices</span> method of Startup class.</p>

<pre><code class="language-code"> services.AddSingleton&lt;ComputerVisionService&gt;();

</code></pre>

<h2 id="creating-the-blazor-ui-component">Creating the Blazor UI Component</h2>

<p>We will add the Razor page in the <span style="color:yellow;background-color:black;">BlazorComputerVision/Pages</span> folder. By default, we have “Counter” and “Fetch Data” pages provided in our application. These default pages will not affect our application but for the sake of this tutorial, we will delete fetchdata and counter pages from <span style="color:yellow;background-color:black;">BlazorComputerVision/Pages</span> folder.</p>

<p>Right-click on the <span style="color:yellow;background-color:black;">BlazorComputerVision/Pages folder</span> and then select Add » New Item. An “Add New Item” dialog box will open, select “Visual C#” from the left panel, then select “Razor Component” from the templates panel, put the name as <span style="color:yellow;background-color:black;">OCR.razor</span>. Click Add. Refer to the image shown below.</p>

<p><img src="/img/azure/10/CreateRazorComponent.png" alt="image info" /></p>

<p>We will add a code-behind file for this razor page to keep the code and presentation separate. This will allow easy maintenance for the application.  Right-click on the <span style="color:yellow;background-color:black;">BlazorComputerVision/Pages</span> folder and then select Add » Class. Name the class as <span style="color:yellow;background-color:black;">OCR.razor.cs</span>. The Blazor framework is smart enough to tag this class file to the razor file. Refer to the image shown below.</p>

<p><img src="/img/azure/10/OCRStuct.png" alt="image info" /></p>

<h2 id="blazor-ui-component-code-behind">Blazor UI component code behind</h2>
<p>Open the  <span style="color:yellow;background-color:black;">OCR.razor.cs</span> file and put the following code inside it.</p>

<pre><code class="language-code">  using Microsoft.AspNetCore.Components;
  using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Threading.Tasks;
  using System.IO;
  using BlazorComputerVision.Models;
  using BlazorInputFile;
  using BlazorComputerVision.Data;
  namespace BlazorComputerVision.Pages
  {
      public class OCRModel : ComponentBase
      {
          [Inject]
          protected ComputerVisionService computerVisionService { get; set; }
          protected string DetectedTextLanguage;
          protected string imagePreview;
          protected bool loading = false;
          byte[] imageFileBytes;
          const string DefaultStatus = "Maximum size allowed for the image is 4 MB";
          protected string status = DefaultStatus;
          protected OcrResultDTO Result = new OcrResultDTO();
          private AvailableLanguage availableLanguages;
          private Dictionary&lt;string, LanguageDetails&gt; LanguageList = new Dictionary&lt;string, LanguageDetails&gt;();
          const int MaxFileSize = 4 * 1024 * 1024; // 4MB
          protected override async Task OnInitializedAsync()
          {
              availableLanguages = await computerVisionService.GetAvailableLanguages();
              LanguageList = availableLanguages.Translation;
          }
          protected async Task ViewImage(IFileListEntry[] files)
          {
              var file = files.FirstOrDefault();
              if (file == null)
              {
                  return;
              }
              else if (file.Size &gt; MaxFileSize)
              {
                  status = $"The file size is {file.Size} bytes, this is more than the allowed limit of {MaxFileSize} bytes.";
                  return;
              }
              else if (!file.Type.Contains("image"))
              {
                  status = "Please uplaod a valid image file";
                  return;
              }
              else
              {
                  var memoryStream = new MemoryStream();
                  await file.Data.CopyToAsync(memoryStream);
                  imageFileBytes = memoryStream.ToArray();
                  string base64String = Convert.ToBase64String(imageFileBytes, 0, imageFileBytes.Length);
                  imagePreview = string.Concat("data:image/png;base64,", base64String);
                  memoryStream.Flush();
                  status = DefaultStatus;
              }
          }
          protected private async Task GetText()
          {
              if (imageFileBytes != null)
              {
                  loading = true;
                  Result = await computerVisionService.GetTextFromImage(imageFileBytes);
                  if (LanguageList.ContainsKey(Result.Language))
                  {
                      DetectedTextLanguage = LanguageList[Result.Language].Name;
                  }
                  else
                  {
                      DetectedTextLanguage = "Unknown";
                  }
                  loading = false;
              }
          }
      }
  }

</code></pre>

<p>We are injecting the <span style="color:yellow;background-color:black;">ComputerVisionService</span> in this class.</p>

<p>The <span style="color:yellow;background-color:black;">OnInitializedAsync</span> is a Blazor lifecycle method which is invoked when the component is initialized. We are invoking the <span style="color:yellow;background-color:black;">GetAvailableLanguages</span> method from our service inside the <span style="color:yellow;background-color:black;">OnInitializedAsync</span> method. We will then initialize the variable <span style="color:yellow;background-color:black;">LanguageList</span> which is a dictionary to hold the details of available languages.</p>

<p>Inside the <span style="color:yellow;background-color:black;">ViewImage</span> method, we will check if the uploaded file is an image only and the size is less than 4 MB. We will transfer the uploaded image to the memory stream. We will then convert that memory stream to a byte array. To set the image preview, we will convert the image from byte array to a base64 encoded string. The <span style="color:yellow;background-color:black;">GetText</span> method will invoke the <span style="color:yellow;background-color:black;">GetTextFromImage</span> method from the service and pass the image byte array as an argument. We will search for the language name from the dictionary based on the language code returned from the service. If no language code is available, we will set the language as unknown.</p>

<h2 id="blazor-ui-component-template">Blazor UI component template</h2>

<p>Open the <span style="color:yellow;background-color:black;">OCR.razor</span> file and put the following code inside it.</p>

<pre><code class="language-code">  @page "/computer-vision-ocr"
@inherits OCRModel
&lt;h2&gt;Optical Character Recognition (OCR) Using Blazor and Azure Computer Vision Cognitive Service&lt;/h2&gt;
&lt;div class="row"&gt;
    &lt;div class="col-md-5"&gt;
        &lt;textarea disabled class="form-control" rows="10" cols="15"&gt;@Result.DetectedText&lt;/textarea&gt;
        &lt;hr /&gt;
        &lt;div class="row"&gt;
            &lt;div class="col-sm-5"&gt;
                &lt;label&gt;&lt;strong&gt; Detected Language :&lt;/strong&gt;&lt;/label&gt;
            &lt;/div&gt;
            &lt;div class="col-sm-6"&gt;
                &lt;input disabled type="text" class="form-control" value="@DetectedTextLanguage" /&gt;
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="col-md-5"&gt;
        &lt;div class="image-container"&gt;
            &lt;img class="preview-image" src=@imagePreview&gt;
        &lt;/div&gt;
        &lt;InputFile OnChange="ViewImage" /&gt;
        &lt;p&gt;@status&lt;/p&gt;
        &lt;hr /&gt;
        &lt;button disabled="@loading" class="btn btn-primary btn-lg" @onclick="GetText"&gt;
            @if (loading)
            {
                &lt;span class="spinner-border spinner-border-sm mr-1"&gt;&lt;/span&gt;
            }
            Extract Text
        &lt;/button&gt;
    &lt;/div&gt;
&lt;/div&gt;
</code></pre>

<p>We have defined the route for this component. We have inherited the <span style="color:yellow;background-color:black;">OCRModel</span> class which allows us to access the properties and method of this class from the template. Bootstrap is used for designing the UI. We have a text area to display the detected text and a text box to display the detected language. The image tag is used to show the image preview after uploading the image. The <span style="color:yellow;background-color:black;">InputFile</span> component will allow us to upload an image file and invoke the <span style="color:yellow;background-color:black;">ViewImage</span> method as we upload the image.</p>

<h2 id="add-styling-for-the-component">Add styling for the component</h2>

<p>Navigate to <span style="color:yellow;background-color:black;">BlazorComputerVision\wwwroot\css\site.css</span> file and add the following style definition inside it.</p>

<pre><code class="language-code">
  .preview-image {
      max-height: 300px;
      max-width: 300px;
  }
  .image-container{
    display: flex;
    padding: 15px;
    align-content: center;
    align-items: center;
    justify-content: center;
    border: 2px dashed skyblue;
  }

</code></pre>

<h2 id="adding-the-links-in-nav-menu">Adding the links in Nav Menu</h2>

<p>The last step is to add the link of our OCR component in the navigation menu. Open <span style="color:yellow;background-color:black;">BlazorComputerVision/Shared/NavMenu.razor</span> file and add the following code into it.</p>

<pre><code class="language-code">  &lt;li class="nav-item px-3"&gt;
    &lt;NavLink class="nav-link" href="computer-vision-ocr"&gt;
      &lt;span class="oi oi-list-rich" aria-hidden="true"&gt;&lt;/span&gt; Computer Vision
    &lt;/NavLink&gt;
  &lt;/li&gt;
</code></pre>
<p>Remove the navigation links for Counter and Fetch-data components as they are not required for this application.</p>

<h2 id="execution-demo">Execution Demo</h2>

<p>Press F5 to launch the application. Click on the Computer Vision button on the nav menu on the left. On the next page, upload an image with some text in it and click on the “Extract Text” button. You will see the extracted text in the text area on the left along with the detected language for the text. Refer to the image shown below.</p>

<p><img src="/img/azure/10/output3.png" alt="image info" /></p>

<p>Now we will try to upload an image with some French text on it, you can see the extracted text and the detected language as French. Refer to the image shown below.</p>

<p><img src="/img/azure/10/output6.png" alt="image info" /></p>

<h2 id="summary">Summary</h2>

<p>We have created an optical character recognition (OCR) application using Blazor and the Computer Vision Azure Cognitive Service. We have added the feature of uploading an image file using the BlazorInputFile component. The application is able to extract the printed text from the uploaded image and recognizes the language of the text. The OCR API of the Computer Vision is used which can recognize text in 25 languages.</p>

<p>Get the Source code from <a href="https://github.com/girishgodage/BlazorComputerVisionAzureCognitiveServices">GitHub</a> and play around to get a better understanding.</p>]]></content><author><name>Girish Godage</name></author><category term="AzureAI" /><category term="learning" /><summary type="html"><![CDATA[Introduction]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://girishgodage.in/img/azure/10/output.gif" /><media:content medium="image" url="https://girishgodage.in/img/azure/10/output.gif" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Angular 10 Material Datatable Inline HttpClient CRUD Operations using RestFull APIs</title><link href="https://girishgodage.in/blog/angular-httpclient-crud-operations-using-restfull-api" rel="alternate" type="text/html" title="Angular 10 Material Datatable Inline HttpClient CRUD Operations using RestFull APIs" /><published>2020-10-27T02:24:00+00:00</published><updated>2020-10-27T02:24:00+00:00</updated><id>https://girishgodage.in/blog/Ang10MatDatatableCRUD</id><content type="html" xml:base="https://girishgodage.in/blog/angular-httpclient-crud-operations-using-restfull-api"><![CDATA[<h2 id="angular-10-material-datatable-inline-httpclient-crud-operations-using-restfull-apis">Angular 10 Material Datatable Inline HttpClient CRUD Operations using RestFull APIs</h2>

<blockquote>
  <p>In this Angular tutorial, we’ll learn how to use HttpClient module in Angular application to make RESTFull API Ajax calls.</p>
</blockquote>

<p>We’ll set up a <strong>new Angular 10 project</strong> and <strong>create API endpoints</strong> to perform <strong>Create, Read, Update and Delete operations using HTTP</strong> methods using a mock server using the <code>**json-server**</code> package. Using <code>**json-server**</code> we can create a local JSON file which can act as a database for our application. There is no difference between a local mock server and a real database.</p>

<p>We’ll perform <strong>HTTP operation using API endpoints</strong> to <strong>add, edit, delete and get list of items listed in an Angular Material Datatable</strong>.</p>

<p>This Material Datatable will have action column using which user an <strong>Edit or Delete a row</strong>. There will be a form over the table to <strong>Add or Update existing rows</strong> in</p>

<p>After implementation, our application will look like this</p>

<p><img src="/img/angular/12/1.png" alt="image info" /></p>

<p>First, let’s have a look at Angular HttpClient and its features.</p>

<h2 id="what-is-angular-httpclient">What is Angular HttpClient?</h2>

<p>A reactive application like Angular, communicate with server databases to fetch data in form of JSON object using Ajax API calls.</p>

<p>These API Ajex calls use XMLHttpRequest service for old browsers or fetch() methods under the hood.</p>

<p>The HttpClient service provided by Angular’s <code>**@angular/common/http**</code> package provides a simple interface to make HTTP calls with many optimized and efficient browser support features.</p>

<p>Moreover, we can also use RxJS based Observables and operators to handle client-side or server-side errors.</p>

<p>Using Interceptors service we can modify requests and responses of API calls and even cancels them.</p>

<p><strong>Let’s get started!</strong></p>

<h2 id="setup-angular-cli">#Setup Angular CLI</h2>

<p>Angular CLI is the most prefered and official way for creating a new Angular project.</p>

<p>Make sure you have installed the latest version on Angular CLI tool on your system.</p>

<p>Run following npm command to install</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
$ npm install -g @angular/cli
</code></pre></div></div>

<p>For this tutorial, we have installed <strong>v10.1.6</strong></p>

<h2 id="create-a-new-angular-10-project">#Create a new Angular 10 project</h2>

<p>Next, create a new Angular project by running following ng command in the terminal</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ ng new ang-datatable-app

</code></pre></div></div>
<p>On hitting above command, ng CLI will ask few configurational questions</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
? Would you like to add Angular routing? Yes
? Which stylesheet format would you like to use? CSS
</code></pre></div></div>

<p>Now move to the project folder</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
$ cd ang-datatable-app
</code></pre></div></div>

<p>Run the project by executing below command</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
$ ng serve --open
</code></pre></div></div>
<p>As we have created the Angular project successfully, lets mover further to create a dummy mock JSON server.</p>

<h2 id="setup-a-mock-json-server">#Setup a Mock JSON Server</h2>

<p>For testing and learning HttpClient module, we need to test Http methods, which will communicate to the server by calling Rest APIs.</p>

<p>These RESTFull APIs return JSON data which is then consumed by Angular application. This API JSON data may come from any third-party API, Server Database or any local server database.</p>

<p>Here we will create a dummy mock JSON API server using the <code>**json-server**</code> package. using this package we can create a mock server using which we can perform all HTTP methods like <code>**GET**</code>, <code>**POST**</code>, <code>**PUT**</code>, <code>**PATCH**</code> and <code>**DELETE**</code>.</p>

<p>First, install the<code> **json-server**</code> package by running bellow npm command in the terminal window:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ npm install -g json-server
</code></pre></div></div>

<p>After that create a new folder API in the project root and place JSON file data.json at 
<strong>~ang-datatable-app/API/data.json</strong></p>

<p>The <strong>data.json</strong> file will work as RESTfull server. We will add some dummy employeess data. So that will act like a database on which we will perform CRUD operations.</p>

<h2 id="start-json-server">#Start JSON Server</h2>

<p>To start the JSON server using json-server, run following command in a new terminal:&lt;</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
$ json-server --watch ./API/data.json
</code></pre></div></div>
<p>Now you can access our mock server at <strong>http://localhost:3000/employees</strong></p>

<p>Following are the API URLs available on our server:</p>

<ul>
  <li>GET /employees - fetch all employees</li>
  <li>GET /employees/: id - fetch a single employee detail by id</li>
  <li>POST /employees - create a new employee</li>
  <li>PUT /employees/: id - update a employee by id</li>
  <li>PATCH /employees/: id - partially update a employee by  id</li>
  <li>DELETE /employees/:id - delete a employee by id</li>
</ul>

<p>As we are ready with our server, next we will import HttpClientModule in Angular project to use HTTP services.</p>

<blockquote>
  <h1 id="configure-httpclient-in-angular-10-project">Configure HttpClient in Angular 10 project</h1>
</blockquote>

<p>Before using HTTP services, we need to import <code>**HttpClientModule**</code> from <code>**@angular/common/http**</code> class.</p>

<p>Now open the app.module.ts file, then make the following changes:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>// app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';

import { HttpClientModule } from '@angular/common/http';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    HttpClientModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
</code></pre></div></div>

<p>We will add <strong>Angular Material Datatable</strong> to perform CRUD operations on Employees data. So let us install and configure Material UI library in our project.</p>

<h2 id="install-and-setup-angular-material">#Install and Setup Angular Material</h2>

<p>Angular Material is a UI library which provides several easy to use feature components. In this tutorial, we will use Material Datatables to show employees records and perform the various inline operation on employees records.</p>

<p>Run following npm command in terminal to install Material library and answer some configuration answers.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ ng add @angular/material


? Choose a prebuilt theme name, or "custom" for a custom theme: Indigo/Pink        [ Preview: https://material.angular.io?theme=indigo-pink ]
? Set up global Angular Material typography styles? Yes 
? Set up browser animations for Angular Material? Yes

</code></pre></div></div>

<p>To use Material UI components, we need to import modules of components which we are going to use in the application’s module so that these will be available in our class components to use.</p>

<p>As we will be using Material Datatables with pagination, so we need to import <code>**MatTableModule**</code> and <code>**MatPaginatorModule**</code>.</p>

<p>To update and add employees rows we will add Material Form as well, for that we will also import <code>**FormsModule**</code>,<code>**ReactiveFormsModule**</code>, <code>**MatInputModule**</code>, and <code>**MatButtonModule**</code> as well
in the <strong>app.module.ts</strong> file as shown below:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
// app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';

import { HttpClientModule } from '@angular/common/http';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';

import { FormsModule, ReactiveFormsModule } from '@angular/forms';

import { MatTableModule } from '@angular/material/table';
import { MatPaginatorModule } from '@angular/material/paginator';
import { MatInputModule } from '@angular/material/input';
import { MatButtonModule } from '@angular/material/button';


@NgModule({
  declarations: [
    AppComponent    
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    HttpClientModule,
    BrowserAnimationsModule,
    FormsModule,
    ReactiveFormsModule,

    // Material Modules 
    MatTableModule,
    MatPaginatorModule,
    MatInputModule,
    MatButtonModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
</code></pre></div></div>

<h2 id="creating-a-service-to-communicate-server-through-http-methods">#Creating a Service to Communicate Server through HTTP methods</h2>

<p>Now we’ll create a new service to separate all HTTP methods which will communicate to server and do CRUD operations.</p>

<p>Let’s create a new serve HttpDataService under services folder by running following ng command in the terminal window:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ ng generate service services/http-data
</code></pre></div></div>

<p>Above <code>**generate**</code> command will create the <code>**HttpDataService**</code> for us at this location <strong>~src/app/services/http-data.service.ts</strong></p>

<p>Also, create an <strong>Interface class</strong> for <em>Employees</em> data by running following command defining the type of values for employee item.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ ng generate class models/Employee

</code></pre></div></div>

<p>then replace the following content in the newly created file “~/models/<strong>employee.ts</strong>”</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>export class Employee {
    id: number;
    userId: string;
    jobTitleName: string;
    firstName: string;
    lastName: string;
    preferredFullName: string;
    employeeCode: string;
    region: string
    phoneNumber: string;
    emailAddress: string;
}
</code></pre></div></div>

<p>Our service will be going to play an important role in maintaining a connection with the server. Let us dive deep into this file and check what it will have?</p>

<p>Add the server API URL for end-points and define in the <code>**base_path**</code> variable. This is the path which opens up on running our <code>**json-server**</code></p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
  // API path
  base_path = 'http://localhost:3000/employees';
</code></pre></div></div>
<p><em>Note:</em> Make sure your server is still running.</p>

<p>We’ll import these three classes</p>

<p><code>**HttpClient**</code> : This class provides HTTP methods like <code>**get()**</code>, <code>**post()**</code>, <code>**put()**</code> and <code>**delete()**</code>.</p>

<p><code>**HttpHeaders**</code>: For setting request headers in HTTP calls we use this class.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
  // Http Options
  httpOptions = {
    headers: new HttpHeaders({
      'Content-Type': 'application/json'
    })
  }
</code></pre></div></div>
<p><code>**HttpErrorResponse**</code>: Used to efficiently handle errors from client-side or server-side.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  // Handle API errors
  handleError(error: HttpErrorResponse) {
    if (error.error instanceof ErrorEvent) {
      // A client-side or network error occurred. Handle it accordingly.
      console.error('An error occurred:', error.error.message);
    } else {
      // The backend returned an unsuccessful response code.
      // The response body may contain clues as to what went wrong,
      console.error(
        `Backend returned code ${error.status}, ` +
        `body was: ${error.error}`);
    }
    // return an observable with a user-facing error message
    return throwError(
      'Something bad happened; please try again later.');
  };
</code></pre></div></div>

<h2 id="rxjs-functions-and-operators-to-the-rescuespan">#RxJs functions and operators to the rescue&lt;/span&gt;</h2>
<p>&lt;/h4&gt;</p>

<p>The RxJs library provides many useful function and operator which we will use in our service:</p>

<p><code>**Observables**</code>: Observables are used to perform asynchronous tasks like HTTP calls. We can subscribe them to get success or error response. They provide several other features file cancellations and continuous event retrieval, unlike promises.</p>

<p><code>**throwError**</code>: This method is used to intentionally throw an error with a message when an HTTP request fails.</p>

<p><code>**retry()**</code>: The retry operator is used to make HTTP call again for the number of times specified when a call fails due to network server issues.</p>

<p><code>**catchError()**</code>: This method catches the error and throws to errorHandler</p>

<h2 id="defining-crud-methods">#Defining CRUD Methods</h2>

<p>Now we will add the methods to do CRUD operation on emloyees data in our mock server which we created using <code>**json-server**</code>.</p>

<h3 id="create-an-employee">Create an Employee</h3>

<p>The new employee will be created using the <code>**post()**</code> method</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  // Create a new item
  createItem(item): Observable&lt;Employee&gt; {
    return this.http
      .post&lt;Employee&gt;(this.base_path, JSON.stringify(item), this.httpOptions)
      .pipe(
        retry(2),
        catchError(this.handleError)
      )
  }
</code></pre></div></div>

<p>The <code>**createItem()**</code> method is accepting <code>**item**</code> attribute with employee details to add.</p>

<h3 id="retrieve-employee-details">Retrieve Employee Details</h3>

<p>To fetch single employee details we use <code>**get()**</code> method with employee <code>**id**</code> whose detail needs to be checked.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> // Get single employee data by ID
  getItem(id): Observable&lt;Employee&gt; {
    return this.http
      .get&lt;Employee&gt;(this.base_path + '/' + id)
      .pipe(
        retry(2),
        catchError(this.handleError)
      )
  }

</code></pre></div></div>

<h3 id="retrieve-all-employees">Retrieve All Employees</h3>

<p>Similarly, we will make <code>**get**</code> call to fetch all employees list</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  // Get employees data
  getList(): Observable&lt;Employee&gt; {
    return this.http
      .get&lt;Employee&gt;(this.base_path)
      .pipe(
        retry(2),
        catchError(this.handleError)
      )
  }
</code></pre></div></div>
<h3 id="update-single-employee">Update single employee</h3>

<p>The <code>**put()**</code> method will update single employee with id passed</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  // Update item by id
  updateItem(id, item): Observable&lt;Employee&gt; {
    return this.http
      .put&lt;Employee&gt;(this.base_path + '/' + id, JSON.stringify(item), this.httpOptions)
      .pipe(
        retry(2),
        catchError(this.handleError)
      )
  }
</code></pre></div></div>
<h3 id="delete-a-single-employee">Delete a single employee</h3>

<p>The <code>**delete()**</code> HTTP method will delete a single record whose id is passed</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
  // Delete item by id
  deleteItem(id) {
    return this.http
      .delete&lt;Employee&gt;(this.base_path + '/' + id, this.httpOptions)
      .pipe(
        retry(2),
        catchError(this.handleError)
      )
  }
</code></pre></div></div>

<p>After combining all explained code the final <strong>http-data.service.ts</strong> file will look like this:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
// http-data.servie.ts
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders, HttpErrorResponse } from '@angular/common/http';
import { Employee } from '../models/employee';
import { Observable, throwError } from 'rxjs';
import { retry, catchError } from 'rxjs/operators';

@Injectable({
  providedIn: 'root'
})
export class HttpDataService {


  // API path
  base_path = 'http://localhost:3000/employees';

  constructor(private http: HttpClient) { }

  // Http Options
  httpOptions = {
    headers: new HttpHeaders({
      'Content-Type': 'application/json'
    })
  }

  // Handle API errors
  handleError(error: HttpErrorResponse) {
    if (error.error instanceof ErrorEvent) {
      // A client-side or network error occurred. Handle it accordingly.
      console.error('An error occurred:', error.error.message);
    } else {
      // The backend returned an unsuccessful response code.
      // The response body may contain clues as to what went wrong,
      console.error(
        `Backend returned code ${error.status}, ` +
        `body was: ${error.error}`);
    }
    // return an observable with a user-facing error message
    return throwError(
      'Something bad happened; please try again later.');
  };


  // Create a new item
  createItem(item): Observable&lt;Employee&gt; {
    return this.http
      .post&lt;Employee&gt;(this.base_path, JSON.stringify(item), this.httpOptions)
      .pipe(
        retry(2),
        catchError(this.handleError)
      )
  }

  // Get single employee data by ID
  getItem(id): Observable&lt;Employee&gt; {
    return this.http
      .get&lt;Employee&gt;(this.base_path + '/' + id)
      .pipe(
        retry(2),
        catchError(this.handleError)
      )
  }

  // Get employees data
  getList(): Observable&lt;Employee&gt; {
    return this.http
      .get&lt;Employee&gt;(this.base_path)
      .pipe(
        retry(2),
        catchError(this.handleError)
      )
  }

  // Update item by id
  updateItem(id, item): Observable&lt;Employee&gt; {
    return this.http
      .put&lt;Employee&gt;(this.base_path + '/' + id, JSON.stringify(item), this.httpOptions)
      .pipe(
        retry(2),
        catchError(this.handleError)
      )
  }

  // Delete item by id
  deleteItem(id) {
    return this.http
      .delete&lt;Employee&gt;(this.base_path + '/' + id, this.httpOptions)
      .pipe(
        retry(2),
        catchError(this.handleError)
      )
  }
}

</code></pre></div></div>
<h2 id="create-new-pages">#Create new pages</h2>

<p>To show employees data in a table,  we will create a new employees component and update the<strong> app-routing.module.ts</strong> file to open <code>/employees</code> page on application load.</p>

<p>Create the <code>**EmployeesComponent**</code>
by running below generate command:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
$ ng generate component pages/employees
</code></pre></div></div>

<p>Setup the App Routing Module
Now update the <strong>app-routing.module.ts</strong>file with below code.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
// app-routing.module.ts
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { EmployeesComponent } from './pages/employees/employees.component';


const routes: Routes = [
  {
    path: '',
    redirectTo: '/employees',
    pathMatch: 'full'
  },
  {
    path: 'employees',
    component: EmployeesComponent
  }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }
</code></pre></div></div>

<h2 id="using-httpdataservice-in-employees-page">#Using HttpDataService in Employees Page</h2>

<p>As we defined our HttpDataService as <code>**providedIn: 'root'**</code>so we can directly use it in our Angular application. This will share a single instance across the application.</p>

<p>To use service methods in our employee’s page at <strong>~src/app/pages/employees/employees.component.ts</strong>, we need to <code>**impor**t</code> it and then add in component the contractor() method as shown below:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>...
import { HttpDataService } from 'src/app/services/http-data.service';

@Component({
  selector: 'app-employees',
  templateUrl: './employees.component.html',
  styleUrls: ['./employees.component.css']
})
export class EmployeesComponent implements OnInit {

  constructor(private httpDataService: HttpDataService) { }

  ...
}

</code></pre></div></div>
<h2 id="adding-angular-material-datatable">#Adding Angular Material Datatable</h2>

<p>Next, we will add a Datatable with Employees columns and an extra Actions column where we will do inline Edit, Delete and Update operations.</p>

<p>For creating the Material datatable, the <code>**mat-table**</code> directive is used. We are also adding pagination by appending the <code>**mat-paginator**</code> directive just after ending <code>**&lt;/table&gt;**</code> tag.</p>

<p>Update the <strong>employees.component.html</strong> file with below code to build a Material datatable:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
        &lt;!-- Form to edit/add row --&gt;

        &lt;table mat-table [dataSource]="dataSource" class="mat-elevation-z8"&gt;

    &lt;ng-container matColumnDef="id"&gt;
        &lt;th mat-header-cell *matHeaderCellDef&gt; #Id &lt;/th&gt;
        &lt;td mat-cell *matCellDef="let element"&gt;  &lt;/td&gt;
    &lt;/ng-container&gt;

    &lt;ng-container matColumnDef="userId"&gt;
        &lt;th mat-header-cell *matHeaderCellDef&gt; User Id &lt;/th&gt;
        &lt;td mat-cell *matCellDef="let element"&gt;  &lt;/td&gt;
    &lt;/ng-container&gt;

    &lt;ng-container matColumnDef="jobTitleName"&gt;
        &lt;th mat-header-cell *matHeaderCellDef&gt; jobTitle Name &lt;/th&gt;
        &lt;td mat-cell *matCellDef="let element"&gt;  &lt;/td&gt;
    &lt;/ng-container&gt;

    &lt;ng-container matColumnDef="firstName"&gt;
        &lt;th mat-header-cell *matHeaderCellDef&gt; First Name &lt;/th&gt;
        &lt;td mat-cell *matCellDef="let element"&gt;  &lt;/td&gt;
    &lt;/ng-container&gt;

    &lt;ng-container matColumnDef="lastName"&gt;
        &lt;th mat-header-cell *matHeaderCellDef&gt; Last Name &lt;/th&gt;
        &lt;td mat-cell *matCellDef="let element"&gt;  &lt;/td&gt;
    &lt;/ng-container&gt;

    &lt;ng-container matColumnDef="preferredFullName"&gt;
        &lt;th mat-header-cell *matHeaderCellDef&gt; Preferred FullName &lt;/th&gt;
        &lt;td mat-cell *matCellDef="let element"&gt;  &lt;/td&gt;
    &lt;/ng-container&gt;

    &lt;ng-container matColumnDef="employeeCode"&gt;
        &lt;th mat-header-cell *matHeaderCellDef&gt; Employee Code &lt;/th&gt;
        &lt;td mat-cell *matCellDef="let element"&gt;  &lt;/td&gt;
    &lt;/ng-container&gt;

    &lt;ng-container matColumnDef="region"&gt;
        &lt;th mat-header-cell *matHeaderCellDef&gt; Region &lt;/th&gt;
        &lt;td mat-cell *matCellDef="let element"&gt;  &lt;/td&gt;
    &lt;/ng-container&gt;

    &lt;ng-container matColumnDef="phoneNumber"&gt;
        &lt;th mat-header-cell *matHeaderCellDef&gt; Phone Number &lt;/th&gt;
        &lt;td mat-cell *matCellDef="let element"&gt;  &lt;/td&gt;
    &lt;/ng-container&gt;

    &lt;ng-container matColumnDef="emailAddress"&gt;
        &lt;th mat-header-cell *matHeaderCellDef&gt; Email Address &lt;/th&gt;
        &lt;td mat-cell *matCellDef="let element"&gt;  &lt;/td&gt;
    &lt;/ng-container&gt;

    &lt;ng-container matColumnDef="actions"&gt;
        &lt;th mat-header-cell *matHeaderCellDef&gt; Actions &lt;/th&gt;
        &lt;td mat-cell *matCellDef="let element"&gt;
            &lt;a href="javascript:void(0)" (click)="editItem(element)"&gt;Edit&lt;/a&gt; |
            &lt;a href="javascript:void(0)" (click)="deleteItem(element.id)"&gt;Delete&lt;/a&gt;
        &lt;/td&gt;
    &lt;/ng-container&gt;

    &lt;tr mat-header-row *matHeaderRowDef="displayedColumns"&gt;&lt;/tr&gt;
    &lt;tr mat-row *matRowDef="let row; columns: displayedColumns;"
        [ngClass]="{'editable-row': employeeData.id === row.id}"&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;mat-paginator [pageSize]="5" [pageSizeOptions]="[5, 10, 15]" showFirstLastButtons&gt;&lt;/mat-paginator&gt;
&lt;/div&gt;

</code></pre></div></div>

<p>In the last <code>**actions**</code> column there are two actions to <strong>Edit</strong> with <code>**editEmployee()**</code> method and <strong>Delete</strong> with<code> **deleteEmployee()**</code> method for the row.</p>

<p>To add a new row or update the data in the existing row we will add a form above table.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    &lt;form (submit)="onSubmit()" #employeeForm="ngForm"&gt;
        
        &lt;mat-form-field&gt;
            &lt;input matInput placeholder="User Id" name="userId" required [(ngModel)]="employeeData.userId"&gt;
        &lt;/mat-form-field&gt;
        &lt;mat-form-field&gt;
            &lt;input matInput placeholder="Job TitleName" name="jobTitleName" required [(ngModel)]="employeeData.jobTitleName"&gt;
        &lt;/mat-form-field&gt;
        &lt;mat-form-field&gt;
            &lt;input matInput placeholder="first Name" name="firstName" required [(ngModel)]="employeeData.firstName"&gt;
        &lt;/mat-form-field&gt;
        &lt;mat-form-field&gt;
            &lt;input matInput placeholder="Last Name" name="lastName" required [(ngModel)]="employeeData.lastName"&gt;
        &lt;/mat-form-field&gt;
        &lt;mat-form-field&gt;
            &lt;input matInput placeholder="Preferred FullName" name="preferredFullName" required [(ngModel)]="employeeData.preferredFullName"&gt;
        &lt;/mat-form-field&gt;        
        &lt;mat-form-field&gt;
            &lt;input matInput placeholder="Employee Code" name="employeeCode" required [(ngModel)]="employeeData.employeeCode"&gt;
        &lt;/mat-form-field&gt;
        &lt;mat-form-field&gt;
            &lt;input matInput placeholder="Region" name="region" required [(ngModel)]="employeeData.region"&gt;
        &lt;/mat-form-field&gt;
        &lt;mat-form-field&gt;
            &lt;input matInput placeholder="Phone Number" name="phoneNumber" required [(ngModel)]="employeeData.phoneNumber"&gt;
        &lt;/mat-form-field&gt;
        &lt;mat-form-field&gt;
            &lt;input matInput placeholder="Email Address" name="emailAddress" required [(ngModel)]="employeeData.emailAddress"&gt;
        &lt;/mat-form-field&gt;

        &lt;ng-container *ngIf="isEditMode; else elseTemplate"&gt;
            &lt;button mat-button color="primary"&gt;Update&lt;/button&gt;
            &lt;a mat-button color="warn" (click)="cancelEdit()"&gt;Cancel&lt;/a&gt;
        &lt;/ng-container&gt;
        &lt;ng-template #elseTemplate&gt;
            &lt;button mat-button color="primary"&gt;Add&lt;/button&gt;
        &lt;/ng-template&gt;

    &lt;/form&gt;
    

</code></pre></div></div>

<p>The text in form submit button will change based on the boolean value in the <code>**isEditMode**</code> variable.</p>

<h2 id="update-component-class">#Update Component Class</h2>

<p>After adding Material datatable and Form, let us update <strong>employees.component.ts</strong> file with required methods.</p>

<p>First, initialize the Template driven form with the <code>**NgForm**</code></p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  @ViewChild('employeeForm', { static: false })
  employeeForm: NgForm;
</code></pre></div></div>

<p>Import the <code>Employee</code> class which we created and define a new variable <code>employeeData</code> of type <code>Employee</code></p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
employeeData: Employee;

</code></pre></div></div>
<p>Then define the <code>**dataSource**</code> and <code>**displayedColumns**</code> with <code>**MatPaginator**</code> class to build our Datatable</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  dataSource = new MatTableDataSource();
  displayedColumns: string[] = ['id', 'userId', 'jobTitleName', 'firstName','lastName','preferredFullName','employeeCode','region', 'phoneNumber','emailAddress','actions'];
  @ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;
  
</code></pre></div></div>
<p>Then we will add methods to Add, Delete, Edit, Update and Get Employees list in the class file as shown below:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>...
  getAllEmployees() {
    this.httpDataService.getList().subscribe((response: any) =&gt; {
      this.dataSource.data = response;
    });
  }

  editItem(element) {
    this.employeeData = _.cloneDeep(element);
    this.isEditMode = true;
  }

  cancelEdit() {
    this.isEditMode = false;
    this.employeeForm.resetForm();
  }

  deleteItem(id) {
    this.httpDataService.deleteItem(id).subscribe((response: any) =&gt; {

      // Approach #1 to update datatable data on local itself without fetching new data from server
      this.dataSource.data = this.dataSource.data.filter((o: Employee) =&gt; {
        return o.id !== id ? o : false;
      })

      console.log(this.dataSource.data);

      // Approach #2 to re-call getAllEmployees() to fetch updated data
      // this.getAllEmployees()
    });
  }

  addEmployee() {
    this.httpDataService.createItem(this.employeeData).subscribe((response: any) =&gt; {
      this.dataSource.data.push({ ...response })
      this.dataSource.data = this.dataSource.data.map(o =&gt; {
        return o;
      })
    });
  }

  updateEmployee() {
    this.httpDataService.updateItem(this.employeeData.id, this.employeeData).subscribe((response: any) =&gt; {

      // Approach #1 to update datatable data on local itself without fetching new data from server
      this.dataSource.data = this.dataSource.data.map((o: Employee) =&gt; {
        if (o.id === response.id) {
          o = response;
        }
        return o;
      })

      // Approach #2 to re-call getAllEmployees() to fetch updated data
      // this.getAllEmployees()

      this.cancelEdit()

    });
  }
...

</code></pre></div></div>

<p>We are calling <code>HttpDataService</code> methods to communicate with our <code>json-server</code>
After adding the above method the final <strong>employees.component.ts</strong> file will look like this:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
// employees.component.ts
import { Component, OnInit, ViewChild } from '@angular/core';
import { NgForm } from '@angular/forms';
import { HttpDataService } from 'src/app/services/http-data.service';
import * as _ from 'lodash';
import { Employee } from 'src/app/models/employee';
import { MatPaginator } from '@angular/material/paginator';
import { MatTableDataSource } from '@angular/material/table';

@Component({
  selector: 'app-employees',
  templateUrl: './employees.component.html',
  styleUrls: ['./employees.component.css']
})
export class EmployeesComponent implements OnInit {

  @ViewChild('employeeForm', { static: false })
  employeeForm: NgForm;

  employeeData: Employee;

  dataSource = new MatTableDataSource();
  displayedColumns: string[] = ['id', 'userId', 'jobTitleName', 'firstName','lastName','preferredFullName','employeeCode','region', 'phoneNumber','emailAddress','actions'];
  @ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;

  isEditMode = false;

  constructor(private httpDataService: HttpDataService) {
    this.employeeData = {} as Employee;
   }

  ngOnInit(): void {
    // Initializing Datatable pagination
    this.dataSource.paginator = this.paginator;

    // Fetch All Employees on Page load
    this.getAllEmployees();
  }

  getAllEmployees(){
    this.httpDataService.getList().subscribe((response: any) =&gt; {
      this.dataSource.data = response;
    });
  }

  editItem(element) {
    this.employeeData = _.cloneDeep(element);
    this.isEditMode = true;
  }

  cancelEdit() {
    this.isEditMode = false;
    this.employeeForm.resetForm();
  }

  deleteItem(id) {
    this.httpDataService.deleteItem(id).subscribe((response: any) =&gt; {

      // Approach #1 to update datatable data on local itself without fetching new data from server
      this.dataSource.data = this.dataSource.data.filter((o: Employee) =&gt; {
        return o.id !== id ? o : false;
      })

      console.log(this.dataSource.data);

      // Approach #2 to re-call getAllEmployees() to fetch updated data
      // this.getAllEmployees()
    });
  }

  addEmployee() {
    this.httpDataService.createItem(this.employeeData).subscribe((response: any) =&gt; {
      this.dataSource.data.push({ ...response })
      this.dataSource.data = this.dataSource.data.map(o =&gt; {
        return o;
      })
    });
  }

  updateEmployee() {
    this.httpDataService.updateItem(this.employeeData.id, this.employeeData).subscribe((response: any) =&gt; {

      // Approach #1 to update datatable data on local itself without fetching new data from server
      this.dataSource.data = this.dataSource.data.map((o: Employee) =&gt; {
        if (o.id === response.id) {
          o = response;
        }
        return o;
      })

      // Approach #2 to re-call getAllEmployees() to fetch updated data
      // this.getAllEmployees()

      this.cancelEdit()

    });
  }

  onSubmit() {
    if (this.employeeForm.form.valid) {
      if (this.isEditMode)
        this.updateEmployee()
      else
        this.addEmployee();
    } else {
      console.log('Enter valid data!');
    }
  }

}

</code></pre></div></div>

<p>That’s it now run you server by executing <code>**$ json-server --watch ./API/data.json**</code> then run Angular application in another terminal by executing <code>**$ ng serve --open**</code>
You can get source code of this tutorial in my GitHub repo <a href="https://github.com/girishgodage/ang10MatDatatabeCrud">here</a></p>

<p><strong>Conclusion</strong>: In this tutorial, we get to know how to use Http services to make server communication, use get, post, put and delete methods on data server. We use RxJs methods and operators to handle errors and network issues using <code>retry()</code> . Added Angular Material UI library to show data rows in a Datatable. In the Material Datatable, we performed CRUD operation using Inline approach</p>]]></content><author><name>Girish Godage</name></author><category term="AngularTutorial" /><category term="learning" /><category term="programming" /><summary type="html"><![CDATA[Angular 10 Material Datatable Inline HttpClient CRUD Operations using RestFull APIs]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://girishgodage.in/img/angular_logo.png" /><media:content medium="image" url="https://girishgodage.in/img/angular_logo.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>