Friday, 24 March 2023

Read PDF with Azure AI - Form Recognizer in .NET C#

There are multiple ways to read the PDF, In this article, we will discuss Azure AI Form Recognizer. Let's learn how to read PDF in .NET/C# code with Form Recognizer? First of all, let's discuss Form Recognizer.

Form Recognizer is a cloud-based service by Microsoft Azure that allows developers to extract information from Forms and Documents. It includes formats like PDF, Images, and Scanned Documents. Form Recognizer can be accessed through Rest API or SDKs.Net, Python, and Javascript.

Let's first create a form Recognizer in Azure Portal.

Step 1: Go to Azure Portal and create a form recognizer










Step 2: Go to Keys and Endpoint and copy Key and Endpoint and we will use both in the code.


















Step 3: Create your application either console framework or core. You need to add Azure.AI.FormRecognizer Nuget Package in your project. Copy the below code and use it.


In the below sample, I am passing the static Azure Blob PDF path, if you need dynamic PDF, follow the previous article to upload the file in a storage blob and use that URL.


     public async Task<string> Index(IFormFile file)
        {
            var pdfURL = "https://myblog.blob.core.windows.net/sample/Constellation.pdf";
            var uri = new Uri(pdfURL);

            var key = "yourkeyhere";
            var endPoint = "https://yoururl.cognitiveservices.azure.com/";

            AzureKeyCredential credential = new(key);
            var client = new DocumentAnalysisClient(new Uri(endPoint), credential);
            var operation = await client.AnalyzeDocumentFromUriAsync(WaitUntil.Completed, 
            "prebuilt-document", uri);
            var result = operation.Value;

            // Read key Value Pair
            foreach (DocumentKeyValuePair kvp in result.KeyValuePairs)
            {
                if (kvp.Value == null)
                {
                    Console.WriteLine($"  Found key with no value: '{kvp.Key.Content}'");
                }
                else
                {
                    Console.WriteLine($"Found key-value pair:'{kvp.Key.Content}' and " +
                    $"'{kvp.Value.Content}'");
                }
            }
             // Read the tables here
            if (result.Tables.Count > 0)
            {
                for (int i = 0; i < result.Tables.Count; i++)
                {
                    DocumentTable table = result.Tables[i];
                    Console.WriteLine($"  Table {i} has {table.RowCount} rows " +
                        $"and {table.ColumnCount} columns.");

                    foreach (DocumentTableCell cell in table.Cells)
                    {
                        Console.WriteLine($"Cell ({cell.RowIndex}, {cell.ColumnIndex}) " +
                        $"has kind '{cell.Kind}' and content: '{cell.Content}'.");
                    }
                }
            }

            return string.Empty;
        }  

You can see the output in a console window and it will read any PDF you like, This Form Recognzier will cost you around $1.5 for 1000 pages. For detailed pricing, you can follow the Microsoft link below

Form Recognizer Pricing


If you want to read the PDF and image with Azure Cognitive Service, you can follow the below link


Read PDF with Azure Cognitive Service




Upload file to Azure Storage Blob/Container in ASP. Net / C# Code

There are many ways to upload files to Azure Storage. We will discuss 3 different ways today. Before that let's create a storage container on Azure Portal.


1. Create a Storage account in Azure Portal
2. Click on the container, create a new container, and select the public access level.











3. Click on the "Access keys" option and copy the connection string. We will use it in our code.














Let's learn different ways to upload files to Azure Storage. To do so, you need to install Azure.Storage.Blobs package from Nuget and you can run the below code based on your requirements.

1. Upload bytes/base64 string to Azure Storage


     [HttpPost]
public async Task<string> UploadFile(string imageBase64, string fileName) { if (!string.IsNullOrEmpty(imageBase64)) { var bytes = Convert.FromBase64String(imageBase64); var stream = new MemoryStream(bytes); var connectionString = "Default";// pass connectionstring here var blobServiceClient = new BlobServiceClient(connectionString); //replace containername with your container name
                var containerClient = blobServiceClient.GetBlobContainerClient("containername"); if (containerClient == null) { return string.Empty; } var blobClient = containerClient.GetBlobClient(fileName); var result = await blobClient.UploadAsync(stream); return blobClient.Uri.AbsoluteUri; }
return string.Empty; }

2. Upload IFormFile to Azure Storage

      
[HttpPost]
public async Task<string> UploadFile(IFormFile file,string fileName) { if (file != null) { var stream = file.OpenReadStream(); var connectionString = "Default";// pass connectionstring here var blobServiceClient = new BlobServiceClient(connectionString); var containerClient = blobServiceClient.GetBlobContainerClient("containername"); if (containerClient == null) { return string.Empty; } var blobClient = containerClient.GetBlobClient(fileName); var result = await blobClient.UploadAsync(stream); return blobClient.Uri.AbsoluteUri; }

            return string.Empty;
        }

3. Upload Local file to Azure Storage      

[HttpPost] public async Task<string> UploadFile(string fileName) { string localfilePath = "Pass local file path here"; var stream = System.IO.File.OpenRead(localfilePath); var connectionString = "Default";// pass connectsting here var blobServiceClient = new BlobServiceClient(connectionString); var containerClient = blobServiceClient.GetBlobContainerClient("containername"); if (containerClient == null) { return string.Empty; } var blobClient = containerClient.GetBlobClient(fileName); var result = await blobClient.UploadAsync(stream); return blobClient.Uri.AbsoluteUri; }


4. Upload Dynamic Json to Azure Storage

// Replace with your Azure Storage connection string string storageConnectionString = "your_storage_connection_string"; // Create a CloudStorageAccount object from the connection string CloudStorageAccount storageAccount; if (CloudStorageAccount.TryParse(storageConnectionString, out storageAccount)) { // Create a CloudBlobClient object for interacting with Blob storage CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient(); // Replace with your container name CloudBlobContainer container = blobClient.GetContainerReference("your_container_name"); // Create the container if it doesn't already exist await container.CreateIfNotExistsAsync(); // Replace with your blob name CloudBlockBlob blob = container.GetBlockBlobReference("your_blob_name.json"); // Create a dynamic object (for example purposes) dynamic jsonObject = new { Name = "John Doe", Age = 30, Email = "john.doe@example.com" }; // Convert dynamic object to JSON string string jsonContent = JsonConvert.SerializeObject(jsonObject); // Convert JSON string to stream using (MemoryStream ms = new MemoryStream()) { using (StreamWriter writer = new StreamWriter(ms)) { writer.Write(jsonContent); writer.Flush(); ms.Position = 0; // Upload JSON file to Azure Blob Storage await blob.UploadFromStreamAsync(ms); Console.WriteLine("JSON file uploaded successfully."); } } } else { Console.WriteLine("Invalid storage connection string."); }

This is all about this article.


Monday, 20 March 2023

Read PDF text with Azure AI (Azure Cognitive Service)

Azure Cognitive Service makes developer life easy for AI tasks. It provides you with one API Endpoint and with that endpoint, it enables many use cases. 


You can do multiple things with a single cognitive Service like Speech, Text, and Vision use cases.
 
Speech to Text
Transcribe audible speech into readable, searchable text.
Text to Speech
Convert text to lifelike speech for more natural interfaces.
Speech Translation
Integrate real-time speech translation into your apps.

Today, we will create a Vision POC and read PDF/Image files.


Step 1: Create an Azure Cognitive Service in Azure Portal.



Step 2: Click on the Keys and EndPoint option. It will provide you one endpoint and key.











Step 3: Create a new MVC Project and paste the code below in .cshtml file




<form method="post" enctype="multipart/form-data">
    <div class="row">
        <div class="col-8">
            <input type="file" name="file" class="form-control" />
        </div>
        <div class="col-4">
            <button type="submit" class="btn btn-primary">Upload File</button>
        </div>
    </div>
    @ViewBag.extractText
</form>


Step 4: Install Computer Vision Nuget Package









Step 5: Paste the below code in Controller.cs


   public class HomeController : Controller
    {
        private Microsoft.AspNetCore.Hosting.IHostingEnvironment _environment;
    
        public HomeController(Microsoft.AspNetCore.Hosting.IHostingEnvironment hostingEnvironment)
        {
            _environment = hostingEnvironment;
        }

        public IActionResult Index()
        {
            return View();
        }

        [HttpPost]
        public async Task<ActionResult> Index(IFormFile file)
        {
            if (file == null)
            {
                ModelState.Clear();
                ModelState.AddModelError("file", "Please select file first.");
                return View("Index");
            }

            var key = "pass your key here"; 
            var endPoint = "https://write your end point here";

            ComputerVisionClient client = Authenticate(endPoint, key);

            if (file.Length > 0)
            {
                var path = Path.GetFullPath(Path.Combine(Environment.CurrentDirectory, "UploadedFiles"));
                if (!Directory.Exists(path))
                {
                    Directory.CreateDirectory(path);
                }
                using (var fileStream = new FileStream(Path.Combine(path, file.FileName), FileMode.Create))
                {
                    await file.CopyToAsync(fileStream);
                }

            }

            var contentPath = _environment.ContentRootPath + "\\UploadedFiles\\";
            var fileName = contentPath + file.FileName;
            var text = await ReadImage(client, fileName);
            if (string.IsNullOrEmpty(text))
                text = "No text found.";
            ViewBag.extractText = text;
            FileInfo fileInfo = new FileInfo(fileName);
            if (fileInfo.Exists)//check file exsit or not  
            {
                fileInfo.Delete();
            }

            return View("Index");
        }

     
       public ComputerVisionClient Authenticate(string endpoint, string key)
        {
            ComputerVisionClient client =
              new ComputerVisionClient(new ApiKeyServiceClientCredentials(key))
              { Endpoint = endpoint };
            return client;
        }

        public async Task<string> ReadImage(ComputerVisionClient client, string localFile)
        {
            StringBuilder sb = new StringBuilder();

            // Read text from URL
            var textHeaders = await client.ReadInStreamAsync(System.IO.File.OpenRead(localFile));
            // After the request, get the operation location (operation ID)
            string operationLocation = textHeaders.OperationLocation;
            Thread.Sleep(2000);


            const int numberOfCharsInOperationId = 36;
            string operationId = operationLocation.Substring(operationLocation.Length - numberOfCharsInOperationId);

            // Extract the text
            ReadOperationResult results;

            do
            {
                results = await client.GetReadResultAsync(Guid.Parse(operationId));
            }
            while ((results.Status == OperationStatusCodes.Running ||
                results.Status == OperationStatusCodes.NotStarted));

            var textUrlFileResults = results.AnalyzeResult.ReadResults;
            foreach (ReadResult page in textUrlFileResults)
            {
                foreach (Line line in page.Lines)
                {
                    sb.AppendLine(line.Text);

                }
            }
            return sb.ToString();
        }
    }


Step 6: Run the project and upload a PDF file






you can see the output below the button, You can extract Specific text based on your need with custom logic.

If you want to read the specific text, then go for the Form Recognizer option in the Azure AI.


To know more about Cognitive Service, you can follow the below link

Azure Cognitive Service



Monday, 6 March 2023

Generate C#/.NET Class atomically from SQL Script

Let's learn how to generate C# Classes from SQL Scripts. Generate C# classes automatically.


Step 1: Copy the query below and run it in the SQL Editor (New Query).
Step 2: Pass the table name as a parameter and run the query.

You can find the entire class in the output below.

DECLARE @TableName sysname = 'Person' -- Pass Table Name here

DECLARE @Output VARCHAR(MAX) = 'public class ' + @TableName + ' {' SELECT @Output = @Output + ' public ' + ColumnType + NullSign + ' ' + ColumnName + ' { get; set; }' FROM ( SELECT replace(col.name, ' ', '_') ColumnName, column_id ColumnId, CASE typ.NAME WHEN 'bigint' THEN 'long' WHEN 'binary' THEN 'byte[]' WHEN 'bit' THEN 'bool' WHEN 'char' THEN 'string' WHEN 'date' THEN 'DateTime' WHEN 'datetime' THEN 'DateTime' WHEN 'datetime2' THEN 'DateTime' WHEN 'datetimeoffset' THEN 'DateTimeOffset' WHEN 'decimal' THEN 'decimal' WHEN 'float' THEN 'double' WHEN 'image' THEN 'byte[]' WHEN 'int' THEN 'int' WHEN 'money' THEN 'decimal' WHEN 'nchar' THEN 'string' WHEN 'ntext' THEN 'string' WHEN 'numeric' THEN 'decimal' WHEN 'nvarchar' THEN 'string' WHEN 'real' THEN 'float' WHEN 'smalldatetime' THEN 'DateTime' WHEN 'smallint' THEN 'short' WHEN 'smallmoney' THEN 'decimal' WHEN 'text' THEN 'string' WHEN 'time' THEN 'TimeSpan' WHEN 'timestamp' THEN 'long' WHEN 'tinyint' THEN 'byte' WHEN 'uniqueidentifier' THEN 'Guid' WHEN 'varbinary' THEN 'byte[]' WHEN 'varchar' THEN 'string' ELSE 'UNKNOWN_' + typ.name END ColumnType, CASE WHEN col.is_nullable = 1 and typ.name IN ('bigint', 'bit', 'date', 'datetime', 'datetime2', 'datetimeoffset', 'decimal', 'float', 'int', 'money', 'numeric', 'real', 'smalldatetime', 'smallint', 'smallmoney', 'time', 'tinyint', 'uniqueidentifier') THEN '?' ELSE '' END NullSign FROM sys.columns col INNER JOIN sys.types typ on col.system_type_id = typ.system_type_id AND col.user_type_id = typ.user_type_id WHERE object_id = object_id(@TableName) ) temp order by ColumnId set @Output = @Output + ' }' print @Output
Here is the output













If you want to generate the entire database classes in a single go then follow the below article

Generate C# classes of the entire database


I hope you like this article.


Saturday, 4 February 2023

Send an email through Gmail SMTP and discuss common errors


This article will teach us how to send emails through the .Net C# code. Common issue while sending an email.

Below is the code to send an email.

Host: smtp.gmail.com
Port: 587


 var client = new SmtpClient("smtp.gmail.com", 587)
            {
                Credentials = new NetworkCredential("senderemal@gmail.com", "password"),               
                EnableSsl = true
            };
  client.Send("senderfromemail@gmail.com", "to@gmail.com", "test", "testbody");


You will get the below error while running this code.

The SMTP server requires a secure connection or the client was not authenticated. The server response was: 5.7.0 Authentication


Upto last year's user, you can enable Less secure app access from Google account settings and run the code. But, now Google no longer supports third-party apps on the devices. Google disables the Less secure app access option.





















To fix this issue, you need to create an app password from the google account settings. 


Step 1: 
Go to your Google Account.

Step 2: Select Security.
Step 3: Under "Signing in to Google," select App Passwords















If the select App password option is unavailable, this means you have not enabled 2-Step verification.

Step 4: Enable the 2-Step verification first.
Step 5: Click on the app password and generate your new password. Select the device and choose the device you’re using and then Generate.






 The App Password is the 16-character code in the yellow bar on your device.
Tap Done.

Step 6: Use your new password in the same code.

 var client = new SmtpClient("smtp.gmail.com", 587)
            {
                Credentials = new NetworkCredential("senderemal@gmail.com", "apppassword"),               
                EnableSsl = true
            };
  client.Send("passfromemail@gmail.com", "to@gmail.com", "Subject", "Email body");


You can find, your email is working

If you want to send an email with HTML Content the use below code.

      var body = "Email body here.<br/><br/> <a>Reset password</a>";
           
      var msg = new MailMessage();    
      msg.IsBodyHtml = true;
      msg.Body = body;
      msg.Subject = "Subject here";
      msg.From = new MailAddress("fromemail@gmail.com");
      msg.To.Add("toemail@gmail.com");

      client.Send(msg);


I hope you like the article.

Thursday, 2 February 2023

YouTube: Unsubscribe all the channels in one go (Mass Un Subscribe)

 

Let's learn how to unsubscribe from all the channels in one go. YouTube does not provide a feature to unsubscribe from all the channels. You can run the script manually to unsubscribe from all the channels.


Step 1: Go to YouTube
Step 2: Click on the Subscriptions on the left panel.

Step 3: Click on the Manage button on the top right.











Step 4: Right-click on the page and click Inspect






















Step 5: Go to the Console tab and paste the below script and press enter














var num = 0;
var myVar = setInterval(unSubscribe, 3000);
function unSubscribe () 
{
  var ele = document.getElementById('grid-container').getElementsByClassName('ytd-expanded-shelf-contents-renderer');
if (num < ele.length) 
{
ele[num].querySelector("[aria-label^='Unsubscribe from']").click();
setTimeout(function () 
{
document.getElementsByClassName('yt-spec-button-shape-next yt-spec-button-shape-next--text yt-spec-button-shape-next--call-to-action yt-spec-button-shape-next--size-m')[0].click()
}, 2000);
}
num++;
console.log(num + " unsubscribed");
console.log(ele.length + " Total");
}


The system will start unsubscribing the channel. 












If you have more than 70 subscribe channels. then you can rerun the script once the script is over. Default, it will pick the first 60-100 records.


That's all about this article. 

Sunday, 8 January 2023

A list of common migration errors from .Net Core 2 or .Net Core 3.1 to .Net 6 or .Net 7

You may encounter these errors when migrating your project to .Net 6 or .Net 7. Below is the error.

1.  'The ConnectionString property has not been initialized.'

In .Net 6 or 7, use has to use the keyword ConnectionStrings instead of ConnectionString otherwise you will get an error, connection string property has not been initialized.







2. A connection was successfully established with the server, but then an error occurred during the login process. (provider: SSL Provider, error: 0 - The certificate chain was issued by an authority that is not trusted.)'


If you are getting the above error this means you need to make the connection string encrypted false in app settings. 











3. An unhandled exception occurred while processing the request. InvalidOperationException: Unable to resolve service for type 'Service.IService' while attempting to activate


In .Net 6 or 7, we don’t have a start-up file. So, you must include everything in Program.cs. file


// Register interface and classes

builder.Services.AddScoped<IHotelService, HotelService>();

 

In Program.cs file, Register dependency before builder.build() command. It will resolve your issue.











4. InvalidOperationException: Unable to resolve service for type 'Data.LocatorDBContext' while attempting to activate 'Service.HotelService'. or
System.AggregateException: 'Some services are not able to be constructed


If you are facing the above issue this means you have not resolved the context in the program.cs and have not included the connection string in the Program.cs. Add the below lines and it will resolve the dependency.

 

builder.Services.AddDbContext<LocatorDBContext>(options =>

        options.UseSqlServer(builder.Configuration.GetConnectionString("LocatorDB")));







For UseSQLserver keyword, you need to include Nuget package.


Microsoft.EntityFrameworkcore.SQLServer


5. System.InvalidOperationException: 'No service for type 'Microsoft.AspNetCore.Mvc.ViewFeatures.ITempDataDictionaryFactory' has been registered.'

This means you have not registered MVC views in Program.cs file. Just add the below line in program.cs file. 


builder.Services.AddControllersWithViews();














6. No web page was found for the web address: http://localhost:5242/hotel/index


This error will occur if you have not registered routing in the program.cs file. Include the below line and it will work.

 

app.MapControllerRoute(

    name: "default",

    pattern: "{controller=Hotel}/{action=Index}/{id?}");












This will resolve the issue. I hope you like the article.

How to get PowerBI Embed Token

 Here's a step-by-step guide to help you through the process. Step 1: Register Your App in Azure 1. Go to Azure Portal → App registratio...