European ASP.NET 4.5 Hosting BLOG

BLOG about ASP.NET 4, ASP.NET 4.5 Hosting and Its Technology - Dedicated to European Windows Hosting Customer

European ASP.NET Core 9.0 Hosting - HostForLIFE :: ASP.NET Core 8 Logging Made Simpler with Serilog and AppInsight

clock September 3, 2024 07:06 by author Peter

Logs are a crucial component of application development since they let you keep an eye on and diagnose issues and defects in your program. Developers love Serilog because it offers organized logging, which makes it easy to find and fix problems. A diagnostic logging library called Serilog was created especially for.NET applications. This method of logging application events, failures, and other pertinent data is straightforward, adaptable, and effective. Support for structured logging, which enables developers to log rich, structured data rather than just plain text messages, is one of Serilog's main advantages.

This post will teach us how to use Serilog with sink AppInsights for application logging in an ASP.NET Core Web API project. Let's now proceed to using Verilog to develop application logging using stages.

Step 1: If your project requires the use of AppInsights for Serilog logging, create a new ASP.NET Core Web API application (.NET8) or utilize an already-existing one.

Give the project name, select the location of the project, and Click on Next.

Select project framework: .NET 8, as depicted below.

Step 2. Install the following packages in your project from the NuGet package manager.

  • Serilog
  • Serilog.AspNetCore
  • Serilog.Sinks.File
  • Serilog.Sinks.ApplicationInsights

Step 3. After the installation of the necessary packages, we will need to configure Serilog in the appsetting.json file. Implementing logging with Verilog in local files and Appinsights is almost similar. However, there are some changes, such as in Using, Write To, and so on, which you can see in the below appsetting.json file.

Note. You need to have an Azure subscription and have already created application insights for this configuration to work.

"Serilog": {
    "Using": [
        "Serilog.Sinks.ApplicationInsights"
    ],
    "MinimumLevel": {
        "Default": "Information",
        "Override": {
            "Microsoft": "Warning",
            "System": "Warning"
        }
    },
    "WriteTo": [
        {
            "Name": "ApplicationInsights",
            "Args": {
                "connectionString": "",
                "telemetryConverter": "Serilog.Sinks.ApplicationInsights.TelemetryConverters.TraceTelemetryConverter, Serilog.Sinks.ApplicationInsights"
            }
        }
    ],
    "Enrich": [ "FromLogContext" ],
    "Properties": {
        "Application": "Connect.IMS"
    }
},


If you want to log in to the local file, you can refer to the previous article here.

Step 4. In the Program.cs, we will add the Serilog configuration
builder.Host.UseSerilog((context, configuration) =>
    configuration.ReadFrom.Configuration(context.Configuration));


Step 5. Then, above the App.Run() write Serilog middleware.
app.UseSerilogRequestLogging();

Step 6. Then, we can now log in to any C# class.
Below is an example of logging in TestController.
using Microsoft.AspNetCore.Mvc;
namespace SampleLogger.Controllers;
[ApiController]
[Route("[controller]")]
public class TestController :  ControllerBase
{
    private readonly ILogger<TestController> _logger;
    public TestController(ILogger<TestController> logger)
    {
        _logger = logger;
    }
    [HttpGet]
    [ProducesResponseType(StatusCodes.Status200OK)]
    public IActionResult Get()
    {
        _logger.LogInformation("Test Controller called!");
        return Ok();
    }
}


Now, we can run the application and check the logs in application insights.

Conclusion

By integrating Serilog to produce more thorough and useful log data, developers can enhance debugging, monitoring, and system maintenance. Because of its structured logging features, Serilog is crucial for contemporary applications as they facilitate log analysis and visualization. The traceability, dependability, and general performance of your application can all be greatly enhanced by using Serilog. This tutorial taught us how to use Application Insights and Serilog to log apps. I hope it's useful to you.



European ASP.NET Core 9.0 Hosting - HostForLIFE :: Caching Singleton Patterns in ASP.NET C#

clock August 27, 2024 07:25 by author Peter

Let's look at an example of implementing the Singleton Design Pattern Real-Time Example Caching in C#. Stated otherwise, the class will be designed as a Singleton and will include the basic Caching capabilities. As a result, by using the Singleton instance, we may add elements to the cache, update the cache, retrieve elements from the cache, delete a specific element from the cache, and remove all elements from the cache.

In our post on Singleton vs. Static Class, we discussed how a Singleton class can inherit from another class, whereas a Static class can never inherit from another class. Let's now examine the inheritance mechanism used in this Caching Example's Singleton class.

Make the Cache Interface
The first step is to copy and paste the code below into the ICacheService.cs class file. This interface describes the operations required for caching. As you can see, we are using the object as the argument for both keys and values in order to store any data in the Cache.

public interface ICacheService
{
    bool Add(object key, object value);

    bool AddOrUpdate(object key, object value);

    object Get(object key);

    bool Remove(object key);

    void Clear();
}


Creating the Singleton Class
The Singleton Class must now be created by deriving from the ICacheService interface mentioned above and providing an implementation for each of the five interface methods. In order to use the following code, create a class file called CacheService.cs and copy and paste it.
public sealed class CacheService : ICacheService
{
    // Concurrent Dictionary Collection is Thread-Safe;
    // yet, it is a shared resource that requires protection in a multithreaded environment.
    private ConcurrentDictionary<object, object> _concurrentDictionary = new();

    // Initializing the variable during class startup and preparing it for use later on,
    // this variable will hold the Singleton Instance.
    private static readonly CacheService _cacheService = new();

    // The Singleton Instance will be returned by the subsequent Static Method.
    // A thread-safe method that makes use of eager loading
    public static CacheService GetInstance()
    {
        return _cacheService;
    }

    // To prevent class instantiation from outside of this class, the constructor must be private.
    private CacheService()
    {
        Console.WriteLine("Singleton cache instance created.");
        Console.WriteLine();
    }

    // The Singleton Instance can be used to access the following methods from outside of the class.

    // A Key-Value Pair can be added to the Cache using this function.
    public bool Add(object key, object value)
    {
        return _concurrentDictionary.TryAdd(key, value);
    }

    // A Key-Value Pair can be added or updated into the Cache using this function.
    // Add the key-value pair if the key is unavailable.
    // Update the key's value if it has already been added.
    public bool AddOrUpdate(object key, object value)
    {
        if (_concurrentDictionary.ContainsKey(key))
        {
            _concurrentDictionary.TryRemove(key, out _);
        }

        return _concurrentDictionary.TryAdd(key, value);
    }

    // If the specified key is in the cache, this function is used to return its value.
    // If not, return null.
    public object Get(object key)
    {
        if (_concurrentDictionary.ContainsKey(key))
        {
            return _concurrentDictionary[key];
        }

        return null!;
    }

    // Using this technique, the specified key is deleted from the cache.
    // Return true if removed; return false otherwise.
    public bool Remove(object key)
    {
        return _concurrentDictionary.TryRemove(key, out _);
    }

    // Using this technique, the specified key is deleted from the cache.
    // Return true if removed; return false otherwise.
    public void Clear()
    {
        // Eliminates every key and value from the Cache, or the ConcurrentDictionary.
        _concurrentDictionary.Clear();
    }
}


Code Explanations

  • To prevent Thread-Safety Problems when executing the program in a Multithreaded Environment, we have implemented the Singleton Design Pattern using Eager Loading in the CacheService class mentioned above.
  • Here, we store the data using key-value pairs in the ConcurrentDictionary collection. This will function similarly to a cache. We utilize the ConcurrentDictionary collection rather than the Generic Dictionary because it is by default thread-safe, meaning that we won't have any thread-safety problems while utilizing a multithread environment.
  • The Key and Value are expected parameters for the Add method. If the key does not already exist in the collection, it then adds the key and values to the ConcurrentDictionary collection. It won't add if the key already exists; in that case, it will return False.
  • The Key and Value are additional parameters that the AddOrUpdate function requires. If the key does not already exist in the collection, it then adds the key and values to the ConcurrentDictionary collection. If the key already exists, it will update the value with the new value that was received.
  • Based on the supplied key, the Get method will return the value. It returns null if the key is not present in the collection.
  • The Remove function returns true after removing the key from the Collection or Cache. It will return false if the key is not present.
  • Every key and value in the collection will be eliminated using the Clear technique.

Utilizing Caching and Singleton Instance in Client Code
The Client Code will be the Program class in our case. To learn how to do caching using the singleton class, let's change the Program class's Main method to use the singleton instance.
const string ID = "Id";
const string NAME = "Name";

// Bring the singleton cache instance
CacheService cache = CacheService.GetInstance();

// Using the Add and AddOrUpdate Method to Add Keys and Values to the Cache
Console.WriteLine("Putting Values and Keys in the Cache");
Console.WriteLine($" Putting Id in Cache: {cache.Add(ID, 1)}");
Console.WriteLine($" Putting Name in Cache: {cache.Add(NAME, "Peter")}");

Console.WriteLine($" Putting Same Id Key in Cache using Add: {cache.Add(ID, 163)}");
Console.WriteLine($" Putting Same Id Key in Cache using AddOrUpdate: {cache.AddOrUpdate(ID, 163)}");

// Using the Get Method and the Keys to access values from the Cache
Console.WriteLine("\nBring Values from Cache");
Console.WriteLine($" Bring Id From Cache: {cache.Get(ID)}");
Console.WriteLine($" Bring Name From Cache: {cache.Get(NAME)}");

// Using the Remove Method to remove elements from the cache by giving the specified keys
Console.WriteLine("\nRemoving Values from Cache");
Console.WriteLine($" Remove Id: {cache.Remove(ID)}");
Console.WriteLine($" Accessing Id From Cache: {cache.Get(ID)}");

// Using the Clear Method to Remove Every Element from the Cache
cache.Clear();
Console.WriteLine("\nClearing All Keys and Values");
Console.WriteLine($" Bring Name From Cache: {cache.Get(NAME)}");


We learned the new technique and evolved together.

Happy coding!



European ASP.NET Core 9.0 Hosting - HostForLIFE :: Real-Time Monitoring of Pageviews Using.NET Core

clock August 22, 2024 06:50 by author Peter

In order to improve and customize user experiences, digital content authors and website managers must have a thorough understanding of how consumers engage with published information. Acknowledging the significance of engagement metrics, it was imperative to put in place a system that tracks and shows the number of page views for every post in real time.

The requirement for this functionality stemmed from several key objectives.

  • Immediate Feedback: Authors and administrators wanted immediate feedback on the performance of newly published articles.
  • User Engagement: Displaying pageview counts can increase transparency and user engagement, as readers can see how popular an article is, potentially influencing their interactions (like comments and shares).
  • Content Strategy Optimization: Real-time data helps in quickly identifying trends and reader preferences, enabling quicker adjustments to content strategy.
  • Enhanced User Experience: Real-time updates contribute to a dynamic and interactive user experience, making the website feel more alive and responsive.

Putting such a feature into practice requires a number of contemporary tools and techniques. We'll use Entity Framework Core for database operations,.NET Core for server-side logic, and SignalR for real-time web functionality in this tutorial. Their strong performance, scalability, and broad community and Microsoft support are the main factors influencing these decisions.

Tools and Technologies

  • .NET Core: A versatile platform for building internet-connected applications, such as web apps and services.
  • Entity Framework Core: An object-database mapper that enables .NET developers to work with a database using .NET objects, eliminating the need for most data-access code.
  • SignalR: A library for ASP.NET developers that simplifies the process of adding real-time web functionality to applications.
  • SQL Database: Utilized to store and retrieve pageview data and article content efficiently.

Implementation Overview
To achieve real-time pageview tracking, we will implement the step-by-step example.
Model Setup: Define a data model for articles that includes a pageview count.
Database Configuration: Set up Entity Framework Core with SQL Server to manage data persistence.
SignalR Integration: Implement a SignalR hub to facilitate the real-time broadcasting of pageview counts to all connected clients.
Incrementing Views: Modify the server-side logic to increment pageview counts upon article access.
Client-Side Updates: Use SignalR on the client side to update the pageview count in real time as users visit the page.

Phase-by-Step Execution
This is how we can put real-time pageview tracking into practice.

Step 1. Define the Article Model
First, add a property to track page visits in the updated model.

public class Article
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }
    public int PageViews { get; set; } // Tracks the number of views
}

Step 2. Configure Entity Framework Core
Configure Entity Framework Core in the Startup.cs to include our database context with SQL Server.
public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
    services.AddControllersWithViews();
    services.AddSignalR();
}

Step 3. Implement SignalR Hub
Create a SignalR hub that manages the broadcasting of pageview updates to connected clients.
public class PageViewHub : Hub
{
    public async Task UpdatePageViewCount(int articleId, int pageViews)
    {
        await Clients.All.SendAsync("ReceivePageViewUpdate", articleId, pageViews);
    }
}

Step 4. Increment Pageviews in Controller
Modify the controller to increment the pageview count each time an article is viewed and notify clients using SignalR.
public async Task<IActionResult> ViewArticle(int id)
{
    var article = await _context.Articles.FindAsync(id);
    if (article == null)
    {
        return NotFound();
    }
    article.PageViews++;
    _context.Update(article);
    await _context.SaveChangesAsync();
    await _hubContext.Clients.All.SendAsync("ReceivePageViewUpdate", article.Id, article.PageViews);
    return View(article);
}

Step 5. Update Client-Side Code
On the client side, use SignalR JavaScript client to update the pageview count in real time.
@section Scripts {
    <script src="~/lib/signalr/signalr.min.js"></script>
    <script>
        var connection = new signalR.HubConnectionBuilder().withUrl("/pageViewHub").build();
        connection.on("ReceivePageViewUpdate", function (articleId, pageViews) {
            var pageViewElement = document.getElementById("page-views-" + articleId);
            if (pageViewElement) {
                pageViewElement.innerText = pageViews + " Views";
            }
        });
        connection.start().catch(function (err) {
            return console.error(err.toString());
        });
    </script>
}


Conclusion
Now that real-time pageview monitoring is included, the platform can provide a more responsive and dynamic user experience. This feature improves user engagement while also offering insightful data that aids in the development of successful content initiatives. By utilizing contemporary technologies such as SignalR and.NET Core, we can maintain our status as a community-driven website that values and reacts to user interactions.



European ASP.NET Core 9.0 Hosting - HostForLIFE :: Studying API Gateway in Micro Services

clock August 12, 2024 09:30 by author Peter

We shall discover what an API gateway is and why we require one in this post.

What is API Gateway?
Consider applications running in a microservice arch so each microservice is deployed individually with its independent URLs. Here, if the application has a lot of microservices, then it will be very difficult for the UI to maintain all URLs of microservices. Here API gateway comes into the picture and behaves as the single entry point for the client and distributes requests to the corresponding micro service.

Flow in API Gateway
Client request: When a request is made from a client, the request first goes to the API gateway, and then the API gateway checks if requesting path and re-routes the request to the corresponding server or microservices.

This diagram shows that all client request goes to the API gateway and then the request goes to microservices.

Use Case 1

Suppose UI has all microservice URLs in their config, in the future if we change the API service URL then all UI code needs to be updated which needs extra effort from UI DEV along with the Backend developer.

Here if we use an API gateway that manages all URLs then the Backend developer is required here we do not need to update the UI so we will save time and cost also.

Use Case 2. Performance Metric
As this is a single entry point for all clients' requests this is the best place to log all requests, here we can measure various metrics like request locations, request count, response time, etc.

Use Case 3. Rate Limiting

With this feature, we can respond back to the client if several requests are more than specific.

For example, suppose we want to implement like, there should be a 1sec interval between 2 requests then we can use this feature and respond back to the client and this will help to refuse of unnecessary requests made by the bot or some software or hacker.

Use Case 4. Authentication

Authentication: as the API gateway is the first entry point for a client we can implement authentication and authorization at this place.
This is no need to apply to auth in each microservice, only request validation is required at the microservice.

API gateway capable of performing below, and these are benefits also,

Use Case 5. Request Composition (Aggregator Pattern)
Consider a scenario where it is requested to call multiple microservices from a single place and needs to combine results from all services and respond.
Here various factors need to be considered if we need to make a Sync call or an async call to microservice to get data.
It is a separate topic we need to discuss later on.

Use Case 6. Protocol Transformation and Payload Transformation

Suppose we want to modify a request from the client as per service acceptance. Then we can do it at this Place (API gateway)
In this article, we learn about API gateways and their few use cases.



European ASP.NET Core 9.0 Hosting - HostForLIFE :: Using.NET 9's New GUID

clock August 5, 2024 10:42 by author Peter

Unique identifying codes that ensure uniqueness are referred to as GUIDs (Globally Unique Identifier) and UIDs (Universally Unique Identifiers). They aren't precisely the same, though. In the realm of programming, the term UUID is used widely across many platforms, languages, and environments. Multiple iterations of the UUID standard are used to create distinct IDs. In the Microsoft ecosystem, UUIDs are referred to as GUIDs when they are utilized. This is a result of Microsoft using the UUID version 4 definition. Thus, GUID is included within the more general name UUID.

Why do we use GUID?
The most common use case for GUIDs is to identify unique records, components, or objects across different systems and databases. GUIDs can be used to identify unique records in databases, COM components (in the past), message identifiers in message queuing systems, session IDs and transaction IDs for session management, token identifiers in security and authentication scenarios, and so on.

Current Scenario

In C#, generating GUID is very simple, as shown below.
Guid g = Guid.NewGuid();
Console.WriteLine(g);

Problem
Although we have a guarantee that the GUID generated using the above code will always be unique, there are several use cases where this can be problematic.

Let’s create five different GUIDs.
Console.WriteLine(Guid.NewGuid());
Console.WriteLine(Guid.NewGuid());
Console.WriteLine(Guid.NewGuid());
Console.WriteLine(Guid.NewGuid());
Console.WriteLine(Guid.NewGuid());

Output
d61f4b57-31e9-4158-86a7-104c3cb16875
e7120f4f-bce1-488b-bdb3-4738793525bd
021baa3e-bf52-4d2e-8303-e1bdddea786b
c2e0c9f8-f04d-4d91-928e-cad5aca5b83f
96f8ae8c-808b-4fc1-a9b8-8e3066acdc50

As you can see from the above output, we cannot identify the order of GUIDs. This means we cannot sort on a field that stores GUIDs. This is essential if we store IDs in a database table and need to retrieve them in sorted order.

New Approach

The new approach is to use version 7 of UUID (instead of version 4) to generate GUIDs. Why version 7? Let’s discuss. If you refer to the original documentation of UUID Version 7, you will notice the description saying that it’s a time-ordered value field derived from the widely implemented and well-known Unix Epoch timestamp source, the number of milliseconds since midnight 1 Jan 1970 UTC, leap seconds excluded. Generally, UUIDv7 has improved entropy characteristics over UUIDv1 (Section 5.1) or UUIDv6 (Section 5.6).

The GUIDs have 5 parts (as you can see from the above example output). For UUID version 7, the first 48 bits (out of 128) will represent the Unix timestamp.

Basically, the IDs generated will be in order of time they generated. As a result, we will be able to sort columns storing GUIDs.
Console.WriteLine(Guid.CreateVersion7());
Console.WriteLine(Guid.CreateVersion7());
Console.WriteLine(Guid.CreateVersion7());
Console.WriteLine(Guid.CreateVersion7());
Console.WriteLine(Guid.CreateVersion7());


Output
5dad1927-6f23-4a07-a033-9dadae005ff7
5dad1927-6f23-4fe7-bfac-1f4dbbcd63ce
5dad1927-6f23-48ba-9044-99ba700770d5
5dad1927-6f23-481f-aa80-bbb32c54ec1c
5dad1927-6f23-4f8f-b639-bdff99b44b55

As you can see from the above output, the first few bits (“5dad1927–6f23”) are common, this is because they were created with the same timestamp. In fact, there is an overload of CreateVersion7 which can take the timestamp provider to control the timestamp.

var guid7 = Guid.CreateVersion7(timeProvider.GetUtcNow());


The advantages of using our own timestamp provider include the ability to provide past or future timestamps and using a DI container to provide our own fake provider.

An additional advantage is that we can always extract the date/time from the GUID if needed.

However, please note that from a performance perspective, version 7 takes longer than the existing version. So, if you are creating a large number of GUIDs, it's best to use the existing code and create another column for sorting.

Conclusion
We learned that GUID is an implementation of a specific version of UUID and is very specific to the Microsoft ecosystem. Further, starting from .NET 9, you can use GUIDs that can be sorted and created using a timestamp provider.



European ASP.NET Core 9.0 Hosting - HostForLIFE :: How to Generating PDFs in .NET Core Web API?

clock July 29, 2024 07:51 by author Peter

Web applications frequently need to generate PDF documents on the fly, whether they be invoices, certifications, reports, or some other kind of document. We'll go over how to use the iText7 library to generate PDFs in a.NET Core Web API in this tutorial. To illustrate how to generate a certificate PDF, we will develop a sample project.


Step 1: Create a project for your.NET Core Web API

Make a new project for a web API
To start a new Web API project, open a terminal or command prompt and type the following command.

dotnet new webapi -n PdfGenerationDemo
cd PdfGenerationDemo

Install Necessary NuGet packages
We will use iText7 for PDF generation. Install it using the following command.

dotnet add package itext7

Step 2. Create Your Models
Create a model to represent the data needed for the certificate. Add a new class CertificateModel.cs in the Models folder.
namespace PdfGenerationDemo.Models
{
    public class CertificateModel
    {
        public string Full_Name { get; set; }
        public string University_Name { get; set; }
        public string Mobile_Number { get; set; }
        public string Email { get; set; }
        public string CampName { get; set; }
        public string From_Date { get; set; }
        public string To_Date { get; set; }
        public string Description { get; set; }
        public string Duration { get; set; }
        public string Institute_Name { get; set; }
        public string Nss_Logo { get; set; }
        public string ProfileImageBase64 { get; set; }
    }
}


Step 3. Create Your Controller
Add a new controller CertificateController.cs in the Controllers folder.
using Microsoft.AspNetCore.Mvc;
using PdfGenerationDemo.Models;
using System;
using System.IO;
using System.Threading.Tasks;
using iText.Html2pdf;
using iText.Kernel.Pdf;
namespace PdfGenerationDemo.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class CertificateController : ControllerBase
    {
        [HttpPost]
        [Route("GenerateCertificate")]
        public async Task<IActionResult> GenerateCertificate([FromBody] CertificateModel request)
        {
            if (request == null)
            {
                return BadRequest("Invalid request data.");
            }

            try
            {
                byte[] pdfBytes = GeneratePDF(request);
                string base64String = Convert.ToBase64String(pdfBytes);

                return Ok(new { Success = true, PdfBase64 = base64String });
            }
            catch (Exception ex)
            {
                return StatusCode(500, $"Internal server error: {ex.Message}");
            }
        }
        private byte[] GeneratePDF(CertificateModel request)
        {
            string body = Template_Body(request);
            using (MemoryStream outputStream = new MemoryStream())
            {
                PdfWriter writer = new PdfWriter(outputStream);
                PdfDocument pdfDoc = new PdfDocument(writer);
                pdfDoc.SetDefaultPageSize(iText.Kernel.Geom.PageSize.A4);

                HtmlConverter.ConvertToPdf(body, pdfDoc);

                return outputStream.ToArray();
            }
        }
        private string Template_Body(CertificateModel request)
        {
            string logoBase64 = request.Logo;
            string photoBase64 = Convert.ToBase64String(Convert.FromBase64String(request.ProfileImageBase64));

            return $@"
<html>
<head>
    <style type='text/css'>
        body, html {{
            margin: 0;
            padding: 0;
            width: 100%;
            height: 100%;
            font-family: Georgia, serif;
        }}
        .container {{
            border: 15px solid #888;
            width: 90%;
            margin: 0 auto;
            padding: 20px;
            background-color: white;
            box-shadow: 0 0 10px rgba(0,0,0,0.5);
            text-align: center;
        }}
        .logo img {{
             width: 300px;
             margin-bottom: 15px;
        }}
        .marquee {{
            color: tan;
            font-size: 36px;
            margin: 10px 0;
        }}
        .assignment {{
            font-size: 20px;
            margin: 20px 0;
        }}
        .person {{
            border-bottom: 2px solid black;
            font-size: 24px;
            font-style: italic;
            margin: 20px auto;
            width: 80%;
            display: inline-block;
        }}
        .details {{
            font-size: 18px;
            margin: 20px 0;
        }}
        .photo img {{
            border: 1px solid #ddd;
            border-radius: 100%;
            padding: 0px;
            width: 150px;
        }}
        .reason {{
            margin: 20px 0;
            font-size: 18px;
        }}
        .signature {{
            margin-top: 50px;
            font-size: 18px;
        }}
        .signature .sig-line {{
            border-bottom: 1px solid black;
            width: 50%;
            margin: 20px auto;
        }}
        .footer {{
            font-size: 14px;
            color: #aaa;
            margin-top: 30px;
        }}
    </style>
</head>
<body>
    <div class='container'>
        <div class='logo'>
            <img src='data:image/png;base64,{logoBase64}' alt='Logo'>
        </div>
        <div class='marquee'>
            Certificate of NSS
        </div>
        <div class='assignment'>
            {request.University_Name}
        </div>
        <div class='assignment'>
            This certificate is presented to
        </div>
        <div class='photo'>
            <img src='data:image/jpeg;base64,{photoBase64}' alt='Student Photo'>
        </div>
        <div class='person'>
            {request.Full_Name}
        </div>
        <div class='details'>
            <p>Number: {request.Mobile_Number}</p>
            <p>Email: {request.Email}</p>
            <p>Camp Name: {request.CampName}</p>
            <p>Camp Time: {request.From_Date} To {request.To_Date}</p>
            <p>Description: {request.Description}</p>
        </div>
        <div class='reason'>
            For Participation in Camp of {request.Duration}  With College<br />
        </div>
       <div class='reason'>
               {request.Institute_Name}<br />
       </div>
        <div class='signature'>
            <p>Authorized Signature</p>
            <div class='sig-line'></div>
        </div>
        <div class='footer'>
            <p>© 2024 An Organization. All Rights Reserved.</p>
        </div>
    </div>
</body>
</html>";
        }
    }
}


Step 4. Testing the API
You can test the API using a tool like Postman. Here’s how you can do it.

Run Your Project
dotnet run

Get the Response

The response will contain a base64 encoded string of the generated PDF.

The response will contain a base64 encoded string of the generated PDF.


Conclusion
We have covered in this post how to use the iText7 library to generate PDFs in a.NET Core Web API. We went through how to set up the project, write the controller, create models, and test the API. This method can be expanded upon and altered to suit different use cases requiring the creation of dynamic PDFs.



European ASP.NET Core 9.0 Hosting - HostForLIFE :: How to Building a AI Chatbot with .NET Core?

clock July 23, 2024 08:21 by author Peter

Providing prompt and efficient communication is essential in the quickly changing digital world of today, particularly for educational platforms and technical blogs that serve programmers, students, and IT professionals. Similar to C# Corner, Codingvila is a technical blog that has made a name for itself as a place where computer enthusiasts can go to get help through tutorials, articles, and community assistance. The implementation of an AI chatbot can transform the way users engage with the platform and improve this support system. In order to provide real-time support and interactive learning opportunities, the "Codingvila Chatbot" makes use of.NET Core.

Why a Chatbot?

  • Instant Support: A chatbot can provide immediate answers to common queries, reducing wait times and improving user satisfaction.
  • Scalability: As the user base grows, a chatbot can effortlessly handle multiple queries at once, unlike human counterparts.
  • 24/7 Availability: It offers round-the-clock support, crucial for users in different time zones or those working on projects outside typical office hours.
  • Personalized Learning: The chatbot can recommend articles and tutorials based on the user's past interactions and preferences.
  • Community Engagement: By handling routine questions, the chatbot allows community managers to focus on more complex queries and community-building activities.

Setting Up the Project
Ensure you have the .NET Core SDK installed to begin. Set up a new project using the command line.
dotnet new console -n HostforlifeChatbot
cd HostforlifeChatbot

This creates a basic .NET Core console application which serves as the foundation for our chatbot.

Integrating Microsoft Bot Framework

Utilize Microsoft's Bot Framework for robust chatbot functionalities. Install the necessary packages.
dotnet add package Microsoft.Bot.Builder
dotnet add package Microsoft.Bot.Builder.Integration.AspNet.Core


These tools enable the use of advanced features like dialogues and conversation flows, essential for an interactive chatbot.
Creating the Bot
 
1. Bot Framework Setup
Implement the HostforlifeBot.cs to manage interactions.
using Microsoft.Bot.Builder;
using Microsoft.Bot.Schema;
using System.Threading.Tasks;

public class HostforlifeBot : IBot
{
    public async Task OnTurnAsync(ITurnContext turnContext, CancellationToken cancellationToken = default)
    {
        if (turnContext.Activity.Type == ActivityTypes.Message)
        {
            string userInput = turnContext.Activity.Text;
            string response = ProcessInput(userInput);
            await turnContext.SendActivityAsync(MessageFactory.Text(response), cancellationToken);
        }
    }

    private string ProcessInput(string input)
    {
        if (input.Contains("hello"))
        {
            return "Hello! Welcome to Hostforlife.com, How can I assist you today?";
        }
        else if (input.Contains("help"))
        {
            return "Here are some things you can ask me...";
        }
        else
        {
            return "I'm not sure how to help with that, but I'm learning more every day!";
        }
    }
}


2. Configure Services and Middleware
Adjust Startup.cs to set up services for the bot.
public void ConfigureServices(IServiceCollection services)
{
    services.AddBot<HostforlifeBot>(options =>
    {
        options.State.Add(new ConversationState(new MemoryStorage()));
    });
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.UseDefaultFiles();
    app.UseStaticFiles();
    app.UseBotFramework();
}


Running the Chatbot
Execute the application
dotnet run

Your chatbot, "Hostforlife Chatbot" is now operational locally. It can be extended to support various platforms like Microsoft Teams, Slack, or Facebook Messenger.

Summary

The Hostforlife Chatbot, developed with .NET Core and Microsoft Bot Framework, is designed to enhance the educational resources of Hostforlife by providing an interactive, responsive, and engaging user experience. This AI-driven tool not only supports real-time communication but also encourages an interactive learning environment, making technology more accessible and comprehensible to its audience.

 



European ASP.NET Core 9.0 Hosting - HostForLIFE :: Authentication and Authorization in ASP.NET Core

clock July 17, 2024 08:49 by author Peter

Web application security relies heavily on authentication and authorization to make sure users are who they say they are and to control what actions they can do. Robust means for integrating authorization and authentication into your apps are provided by ASP.NET Core. We'll go into great detail about these ideas in this post, including key elements, recommended procedures, and real-world application examples.

Understanding Authentication and Authorization
Authentication verifies the identity of users attempting to access your application. It answers the question, "Who are you?" Common authentication methods include.

  • Cookie-based Authentication: Uses encrypted cookies to authenticate users.
  • Token-based Authentication: Utilizes JWT (JSON Web Tokens) or OAuth tokens for authentication.
  • External Authentication Providers: Allows users to log in using external providers like Google, Facebook, etc.
  • Windows Authentication: Uses Windows credentials for intranet applications.

Authorization, on the other hand, determines what authenticated users are allowed to do within the application. It answers the question, "What are you allowed to do?" Authorization can be role-based, policy-based, or claim-based, where.
Role-based Authorization: Assigns roles (admin, user, manager) to users and restricts access based on roles.
Policy-based Authorization: Defines access policies that evaluate a combination of roles, claims, and requirements.
Claim-based Authorization: Grants access based on specific claims associated with the user's identity.

Implementing Authentication in ASP.NET Core
Cookie Authentication: Cookie authentication is commonly used for web applications that require user sessions. ASP.NET Core provides built-in middleware to handle cookie-based authentication.
    // Startup.cs
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
            .AddCookie(options =>
            {
                options.Cookie.Name = "YourAppCookie";
                options.LoginPath = "/Account/Login";
                options.AccessDeniedPath = "/Account/AccessDenied";
            });
    }

Token-based Authentication: Token-based authentication is suitable for APIs and single-page applications (SPA). ASP.NET Core supports JWT (JSON Web Tokens) authentication out of the box.
// Startup.cs
public void ConfigureServices(IServiceCollection services)
{
    services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer(options =>
        {
            options.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuer = true,
                ValidateAudience = true,
                ValidateLifetime = true,
                ValidateIssuerSigningKey = true,
                ValidIssuer = Configuration["Jwt:Issuer"],
                ValidAudience = Configuration["Jwt:Issuer"],
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:Key"]))
            };
        });
}

Implementing Authorization in ASP.NET Core: Authorization is configured using policies and requirements. Define policies in Startup.cs and apply them using the [Authorize] attribute in controllers or actions.
// Startup.cs
public void ConfigureServices(IServiceCollection services)
{
    services.AddAuthorization(options =>
    {
        options.AddPolicy("AdminOnly", policy => policy.RequireRole("Admin"));
        options.AddPolicy("MinimumAge", policy =>
            policy.Requirements.Add(new MinimumAgeRequirement(18)));
    });
}
// Controller
[Authorize(Policy = "AdminOnly")]
public IActionResult AdminDashboard()
{
    return View();
}


Summary
In this article, we've explored the fundamentals of authentication and authorization in ASP.NET Core. Understanding these concepts is crucial for building secure and scalable web applications. ASP.NET Core provides flexible and powerful tools to implement various authentication and authorization mechanisms tailored to your application's needs. By leveraging these capabilities effectively, you can ensure that your application remains secure and compliant with modern security standards.

Implementing authentication and authorization involves configuring middleware, defining policies, and applying attributes correctly across your application. Whether you choose cookie-based authentication for web applications or token-based authentication for APIs, ASP.NET Core offers comprehensive support and flexibility to meet your security requirements.

By following best practices and staying updated with the latest security trends, you can build robust and secure ASP.NET Core applications that protect user data and maintain user trust.



European ASP.NET Core 9.0 Hosting - HostForLIFE :: Task: Synchronous vs. Asynchronous.Task and WaitAll.WhenEverything in.NET

clock July 9, 2024 07:09 by author Peter

Asynchronous programming in C# frequently entails doing several tasks at once. Task and Split are two popular approaches to managing many tasks.Task.WhenAll and WaitAll. Despite their apparent similarities, they have different functions and are employed in various contexts. The distinctions between Task.WaitAll and Task.WhenAll are examined in this article, along with real-world examples to show how to use both.


What is Task.WaitAll?
Assignment.The synchronous function WaitAll stops the calling thread after each of the supplied tasks is finished. It's helpful when you have to make sure that a group of tasks is completed before moving on, but it does so in a blocking way, meaning that Task is called by the thread.Until every task is completed, WaitAll is in use.

Example Usage of Task.WaitAll
using System;
using System.Threading.Tasks;
class Program
{
    static void Main()
    {
        Task task1 = Task.Run(() => PerformTask(1));
        Task task2 = Task.Run(() => PerformTask(2));
        Task task3 = Task.Run(() => PerformTask(3));
        Task.WaitAll(task1, task2, task3); // Blocks until all tasks complete
        Console.WriteLine("All tasks completed.");
    }
    static void PerformTask(int taskId)
    {
        Console.WriteLine($"Task {taskId} starting.");
        Task.Delay(1000).Wait(); // Simulate work
        Console.WriteLine($"Task {taskId} completed.");
    }
}


In this example, Task.WaitAll blocks the main thread until all three tasks are complete.

What is Task.WhenAll?

Task.WhenAll is an asynchronous method that returns a single task that is completed when all the provided tasks have been completed. Unlike Task.WaitAll, it does not block the calling thread. Instead, it allows the calling code to continue executing asynchronously.

Example Usage of Task.WhenAll

using System;
using System.Threading.Tasks;
class Program
{
    static async Task Main()
    {
        Task task1 = Task.Run(() => PerformTask(1));
        Task task2 = Task.Run(() => PerformTask(2));
        Task task3 = Task.Run(() => PerformTask(3));
        await Task.WhenAll(task1, task2, task3); // Waits for all tasks to complete asynchronously
        Console.WriteLine("All tasks completed.");
    }
    static void PerformTask(int taskId)
    {
        Console.WriteLine($"Task {taskId} starting.");
        Task.Delay(1000).Wait(); // Simulate work
        Console.WriteLine($"Task {taskId} completed.");
    }
}


In this example, Task.WhenAll allows the main method to await the completion of all tasks without blocking the calling thread.

Key Differences
Blocking vs. Non-blocking

  • Task.WaitAll: Blocks the calling thread until all tasks are complete.
  • Task.WhenAll: Returns a task that can be awaited, allowing the calling thread to continue execution asynchronously.

Return Type

  • Task.WaitAll: Does not return a value.
  • Task.WhenAll: Returns a Task that represents the completion of all provided tasks.

Usage Scenario

  • Task.WaitAll: Used when you need to block until tasks are complete, typically in non-UI or console applications.
  • Task.WhenAll: Used in asynchronous programming, especially in UI applications where blocking the main thread is undesirable.

Practical Use Cases
When to Use Task.WaitAll

  • In console applications where you need to ensure that certain tasks are completed before moving on.
  • When you are dealing with legacy code that doesn’t support async/await patterns.

When to Use Task.WhenAll

  • In UI applications keep the interface responsive.
  • In web applications handle multiple asynchronous operations without blocking the main thread.

Conclusion
Task.WaitAll and Task.WhenAll are essential tools in C# for handling multiple tasks. Use Task.WaitAll when you need to block the calling thread until tasks are complete, and Task.WhenAll for asynchronous waiting. Understanding their differences and appropriate use cases can help you write more efficient and responsive applications.



European ASP.NET Core 9.0 Hosting - HostForLIFE :: Resilience in a.NET 8 Web API Implementation

clock July 2, 2024 08:16 by author Peter

Creating robust APIs is more important than ever in the age of modern web development, especially with all these third-party integration we rely on. In this Blog, We will be guiding you how to introduce resilience in. Create an HTTP Client in a. Extensions. Http. Resilience library. In this section, we will take a look at features like setting up retry policies with exponential backoff and timeouts to make your API more resilient against the transient faults.

Step 1. Create a new. NET 8 Web API project Step First, if you have no existing Project then create new with. NET CLI dotnet new web or starting with the default Web API template.

Step 2. Install the Microsoft.AspNetCore. Extensions. Http. Resilience library via NuGet:
dotnet add package Microsoft.Extensions.Http.Resilience --version 8.0.0

Step 3. Configure Resilience in Program.cs
Modify the Program.cs file to set up HttpClient with resilience policies provided by Microsoft.Extensions.Http.Resilience. Here, we will define retry policies and timeouts.
//Add resilience pipeline
builder.Services.AddResiliencePipeline("default", x =>
{
    x.AddRetry(new Polly.Retry.RetryStrategyOptions
    {
        ShouldHandle = new PredicateBuilder().Handle<Exception>(),
        Delay = TimeSpan.FromSeconds(2),
        MaxRetryAttempts = 2,
        BackoffType = DelayBackoffType.Exponential,
        UseJitter = true
    })
    .AddTimeout(TimeSpan.FromSeconds(30));
});

Step 4. Use the Resilient HttpClient in a Service
Next, we'll inject and use the configured HttpClient in your Service. This example shows how to fetch data from an external API using the resilient HttpClient.
public class WeatherService
{
    private readonly HttpClient _httpClient;
    private readonly ResiliencePipelineProvider<string> _resiliencePipelineProvider;
    public WeatherService(HttpClient httpClient,
                         ResiliencePipelineProvider<string> resiliencePipelineProvider)
    {
        _httpClient = httpClient;
        _resiliencePipelineProvider = resiliencePipelineProvider;

    }
    public async Task<string> GetWeatherAsync()
    {
        var pipeline = _resiliencePipelineProvider.GetPipeline("default");
        var response = await pipeline
            .ExecuteAsync( async ct=> await _httpClient.GetAsync($"https://localhost:7187/weatherforecast",ct));

        return await response.Content.ReadAsStringAsync();
    }

}


Step 5. Add the endpoint in the Program.cs
app.MapGet("/weatherService/weather", async (WeatherService weatherService) =>
{
    var result = await weatherService.GetWeatherAsync();
    return result;
})
    .WithName("GetWeather")
    .WithOpenApi();


Step 6. Run the Application
Finally, run your application and navigate to the endpoint to see the resilient HttpClient in action.
References

Please refer to the below links for more details.

  • Building resilient cloud services with .NET 8
  • Learning from Microsoft

Conclusion
By following these steps, you have integrated resilience into your .NET 8 Web API project using Microsoft.Extensions.Http.Resilience library. The retry policies, circuit breaker settings, and timeouts will help ensure your API is robust against transient faults, improving its reliability and user experience.

 



About HostForLIFE.eu

HostForLIFE.eu is European Windows Hosting Provider which focuses on Windows Platform only. We deliver on-demand hosting solutions including Shared hosting, Reseller Hosting, Cloud Hosting, Dedicated Servers, and IT as a Service for companies of all sizes.

We have offered the latest Windows 2016 Hosting, ASP.NET Core 2.2.1 Hosting, ASP.NET MVC 6 Hosting and SQL 2017 Hosting.


Tag cloud

Sign in