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 8.0.1 Hosting - HostForLIFE :: How to Frozen Collections in .NET 8?

clock June 11, 2024 10:38 by author Peter

With the release of .NET 8, Microsoft has introduced several new features and improvements to enhance performance and developer productivity. Among these, one of the most notable additions is the concept of "Frozen Collections." This article explores what frozen collections are, their benefits, and how to use them effectively in your .NET applications.

Frozen Collections: What Are They?
A new kind of immutable collection called frozen collections is intended to improve access speed and reduce memory usage in order to maximize performance. Frozen collections are intentionally made to be immutable from the beginning, in contrast to conventional read-only collections, which are frequently nested inside changeable collections. Once a collection is frozen, its immutability ensures that it cannot be altered, which has various performance benefits.

Key Benefits of Frozen Collections
1. Performance Optimization
The primary advantage of frozen collections lies in their performance. By guaranteeing immutability, the .NET runtime can make several optimizations.

  • Memory Efficiency: Since frozen collections do not change, they can be stored in a compact form, reducing the overall memory footprint.
  • Access Speed: Lookup operations are faster because the underlying data structure can be optimized for read access.
  • Thread Safety: Frozen collections are inherently thread-safe, eliminating the need for synchronization mechanisms when accessing them concurrently.


2. Predictable Behavior
Immutable collections provide predictable behavior, which simplifies debugging and reasoning about code. When a collection is guaranteed not to change, developers can avoid common pitfalls related to concurrent modifications and side effects.

3. Simplified Code

Using frozen collections can lead to cleaner and more maintainable code. Since the collections cannot be altered, functions that operate on them do not need to account for modifications, leading to simpler and more readable implementations.

Using Frozen Collections in .NET 8
To use frozen collections in .NET 8, you can leverage the new FrozenCollection<T> class available in the System.Collections.Immutable namespace. Here’s a basic example to illustrate how to create and use a frozen collection.
using System;
using System.Collections.Immutable;

class Program
{
    static void Main()
    {
        var mutableList = new List<int> { 1, 2, 3, 4, 5 };

        // Create a frozen collection from the mutable list
        var frozenCollection = mutableList.ToFrozenCollection();

        // Attempting to modify the frozen collection will result in a compile-time error
        // frozenCollection.Add(6); // Not allowed

        // Accessing elements is fast and efficient
        Console.WriteLine(frozenCollection[0]); // Output: 1

        // The collection is inherently thread-safe
        Parallel.ForEach(frozenCollection, item => {
            Console.WriteLine(item);
        });
    }
}

public static class Extensions
{
    public static FrozenCollection<T> ToFrozenCollection<T>(this IEnumerable<T> source)
    {
        var builder = new FrozenCollectionBuilder<T>();
        foreach (var item in source)
        {
            builder.Add(item);
        }
        return builder.ToFrozenCollection();
    }
}

Creating a Frozen Collection
In the example above, we start with a mutable list of integers. Using an extension method, we convert this list into a FrozenCollection<T>. The FrozenCollectionBuilder<T> class is used to add elements to the collection before it is frozen.

Accessing Elements

Once the collection is frozen, we can access its elements just like a regular collection. However, any attempt to modify the collection will result in a compile-time error, ensuring immutability.

Thread Safety

The inherent thread safety of frozen collections allows for safe concurrent access without additional synchronization, making them ideal for use in multi-threaded environments.

Conclusion

Frozen collections in .NET 8 represent a significant advancement in collection management, providing developers with powerful tools to create high-performance, immutable data structures. By leveraging these collections, you can achieve better memory efficiency, faster access times, and simplified code. As .NET continues to evolve, features like frozen collections will play a crucial role in enabling developers to build robust and efficient applications.

 



European ASP.NET Core 8.0.1 Hosting - HostForLIFE :: Increasing Code Quality: The Best Methods for Successful Code Reviews

clock June 3, 2024 07:40 by author Peter

Clarify goals and expectations prior to starting a code review. Make sure that the review's goal is understood, whether it is to verify code quality, find errors, impart knowledge, or uphold coding standards. Establishing specific goals guarantees that reviewers concentrate on the most pertinent parts of the code and speeds up the review process.

Specify the codes
Specify recommended practices and coding standards that all developers should follow. This covers standards for code organization, formatting rules, naming conventions, and documentation. Adhering to coding standards consistently makes the codebase easier to read, maintain, and scale, which in turn makes it easier for developers to communicate and work together on code.

Conduct regular reviews
Regularly incorporate code reviews into the development process. Establish systems that enable peer reviews for each code update, such as pull requests or code review software. Frequent reviews guarantee that code quality is maintained at a high level throughout the development process, assist find problems early, and prevent the building of technical debt.

Keep reviews small and focused

Divide code modifications into more digestible, smaller pieces to enable targeted and effective assessments. Big code changes are frequently intimidating and prone to problems that go unnoticed. Smaller, more targeted evaluations allow reviewers to give more insightful criticism and developers to handle issues more skillfully.

Foster a collaborative culture

Encourage a cooperative and positive atmosphere when conducting code reviews. Urge reviewers to focus on the code rather than the developer and to offer constructive criticism in a courteous manner. Promote transparent communication, stimulate dialogue, and take use of evaluations as a means of imparting information and providing mentorship.

Automate where possible
Automate repetitive tasks and checks to streamline the code review process. Use automated tools for static code analysis, code formatting, and unit testing to identify common issues and enforce coding standards automatically. Automation reduces manual effort, improves consistency, and frees up time for reviewers to focus on higher-level concerns.

Prioritize feedback and follow-up

Prioritize feedback based on its severity, impact, and urgency. Address critical issues and blockers promptly to prevent delays in the development process. Keep track of feedback and action items, follow up on unresolved issues, and ensure that all feedback is addressed satisfactorily before closing the review.

Encourage learning and growth
View code reviews as opportunities for learning and professional growth. Encourage developers to seek feedback, ask questions, and engage in discussions to deepen their understanding of coding principles and best practices. Provide constructive feedback, mentorship, and guidance to help developers improve their skills and grow as professionals.



European ASP.NET Core 8.0.1 Hosting - HostForLIFE :: Using and Exercising the String Builder in.NET C#

clock May 27, 2024 07:04 by author Peter

Once a string type is generated in C#, its contents cannot be changed since the string type is immutable. This suggests that modifying a string-type object after it has been created will cause the object to be constructed again in memory as a new instance. Additionally, changing the string frequently could cause performance problems.


StringBuilder solves this problem because, unlike string, it can dynamically increase its memory to support any kind of manipulation.

How to make a StringBuilder correctly?
It is not too difficult to instantiate a StringBuilder. We can instantiate a class by using the new keyword to create an instance of that class. A StringBuilder also contains other constructors.

Conversion of StringBuilder to String
We can use a StringBuilder for any type of string manipulation. But the StringBuilder does not return a string. Therefore, in order to retrieve a string, we must use the ToString() method.
var sb = new StringBuilder("Peter Scott");

var name = sb.ToString();

The content is first converted to a string and then a StringBuilder is created with a default text.

StringBuilder Techniques

We can work with a StringBuilder's contents in a few different ways. These include Replace(), Insert(), Clean(), Remove(), Append(), AppendLine(), and AppendFormat().

Append
A new string is appended to the end of the existing StringBuilder using the Append() function. The StringBuilder's length can be doubled, and space allocation happens automatically.
var sb = new StringBuilder("Hello, ");
sb.Append("Peter Scott");
var name = sb.ToString();

Console.WriteLine("{0} - {1}", nameof(name), name);

AppendLine
AppendLine() is useful when we want to add a line terminator to our StringBuilder. To accomplish this, we can make a StringBuilder and use the following method.


var sb = new StringBuilder("Hello, ");
sb.Append("Peter Scott");
sb.AppendLine();
sb.AppendLine("How are you?");

Console.WriteLine(sb.ToString());

AppendFormat
AppendFormat() appends a string to the end of StringBuilder in a predetermined format. The conventions of either the chosen culture or the current system culture are revealed in the produced string. The method lets us pass the desired format for our string as an input.
var sb = new StringBuilder("Hello, ");
sb.Append("Peter Scott");
var text = "C# Corner Rank";
var rank = 120;
sb.AppendLine();
sb.AppendFormat("{0} - {1}", text, rank);

Console.WriteLine(sb.ToString());


This method adds, to our StringBuilder object, a string, substring, character array, part of a character array, or the string representation of a primitive data type at a certain place. We may also add the index for our insertion using this method.
var sb = new StringBuilder("Hello");
var name = ", Peter Scott";
sb.Insert(5, name);

Console.WriteLine(sb.ToString());


Replace
Several character occurrences in the StringBuilder object are replaced by this method. The desired character sequence and a new value are entered into the method as inputs.
var sb = new StringBuilder("Hello");
var name = ", Peter Scott";
sb.Insert(5, name);
Console.WriteLine("Orioginal data: {0}", sb.ToString());
Console.WriteLine();

sb.Replace("Lee", "Cooper");

Console.WriteLine("Replace data: {0}", sb.ToString());


Replace
A predetermined amount of characters are removed from the StringBuilder using the Remove() function. The start index and the number of characters to be deleted are the input parameters.

var sb = new StringBuilder("Hello");
sb.Append(", Peter Scott");

Console.WriteLine("Orioginal data: {0}", sb.ToString());
Console.WriteLine();

sb.Remove(0, 7);

Console.WriteLine("Remove data: {0}", sb.ToString());


Remove
The Remove technique eliminates 7 characters starting at index 0.

Clear

The StringBuilder object's characters are all eliminated using this function. This method reduces the length of a StringBuilder to zero.
var sb = new StringBuilder("Hello");
sb.Append(", Peter Scott");

Console.WriteLine("Orioginal data: {0}", sb.ToString());
Console.WriteLine();

sb.Clear();

Console.WriteLine("Clear data: {0}", sb.ToString());


Clear
We learned the new technique and evolved together.
Happy coding!



European ASP.NET Core 8.0.1 Hosting - HostForLIFE :: The Issue of Thread Synchronization and It's ResolutionAn Alternative View on Stack Memory in.NET

clock May 20, 2024 09:40 by author Peter

We shall discuss the Stack memory in.NET in this article. The portion of memory in.NET that is assigned to a thread is called the Stack. To put it simply, each thread has a stack—that is, its own memory—that is the last in, first out. Note: Because there is a connection between Stack memory and Heap memory, some parts of the article are explained but do not include Heap memory.


Memory Stack
Computer memory architecture is where the idea of a memory stack first appeared. Its essence also affects the various programming languages. After all, in any computer system, a programming language is a form of abstraction or communication. Many programming languages are forced to adopt it as a result.
So, even the CPU has push-and-pop instructions for providing thread (stack) execution and other things. Well, without further confusion, let’s continue our look at .NET and their use of Stack memory.

Nearly all developers are aware that a data structure is referred to as a "stack." There are two general strategies for the stack data structure: FIFO and LIFO. We employ the LIFO (last in first out) method to operate our stack memory. Moreover, distinguish between stack memory and the stack data structure. Because stack memory makes use of the stack data structure technology, names are the same. There are two different kinds of memory in.NET; a heap and a stack, both of which are found in RAM. Method calls, return addresses, arguments/parameters, and local variables are all tracked by the stack. However, reference-type objects are stored in Heap (this is a topic for another article).

To put it simply, every thread has a memory location of its own. This is the stack, which represents each thread's local memory. Thus, during method execution, threads define a local variable, retrieve the result, and then call another method, and so on. It is these actions that require stack memory. Furthermore take note that just one thread of execution uses the stack memory. Conversely, a heap is shared memory used by multiple threads, the extent of which is specified by the operating system process.

Allocation of Stacks
Stack allocation, to put it simply, is a memory allocation technique that makes use of the stack, a section of memory. The most recently allocated memory is the first to be deallocated because, as I previously explained, the stack uses the LIFO (last in first out) method of operation. There are two types in.NET. A reference type is one, and a value type is the other. Thus, the value of the type is saved immediately when allocating a value type in a stack. However, when dealing with reference types that reside in heaps, it stores the heap's reference address, also known as the object's pointer. Generally speaking, it means that a stack only contains values (a reference address is a type of value, but we'll talk about that in another article).

The figure above illustrates how two declared variables are present in a separate stack frame within the thread stack: a flag (int32, value type) and a pInst, instance of the Person class. We won't talk about the heap, but the picture demonstrates that it has the flag's value of 1, as well as the reference address of pInst. The address for the stack that refers the heap object—an object with data and methods stored on the heap—is what is meant to be used in the reference type. In .NET, Stack memory has a fixed size which a 1-MB stack is allocated when a thread is created. This size is predefined once the program starts, providing a consistent amount of stack memory available for function calls and local variable storage. However, the fixed nature of the stack means that it can only hold a limited amount of data. In addition, the speed of stack memory operations is a key advantage based on the simplicity of the stack’s push and pop mechanisms.

So, almost everyone wonders why the Stack memory is fast.

  • Firstly, stack memory uses static memory allocation, meaning that memory is given and taken away in a predictable way. This removes the need for complicated memory management, making operations quick and efficient.
  • Secondly, as I said above the stack has a fixed size, which avoids the overhead of finding available memory space, unlike heap memory. The simple push-and-pop operations also make it faster. These operations just adjust the stack pointer, which is very fast compared to the more complex operations needed for heap memory.
  • Thirdly, modern CPUs have special instructions for stack operations, like pushing and popping data, which are made to be very fast. The CPU also uses a dedicated register, the stack pointer, to efficiently manage the stack’s top position. In addition, stack memory often gets loaded into the CPU cache. This happens because stack data is frequently accessed in a straight line, making it more friendly to the cache. In contrast, accessing heap memory is indirect and can involve more cache misses, making it slower. This direct hardware support and cache efficiency ensure that stack operations have very little overhead.

Stack Frame/Call Stack

A stack frame, also known as an activation record, is a section of the stack memory allocated for a single function/method call. When a function/method is called, a new stack frame is allocated, and when the function/method returns, its stack frame is deallocated.

Basically, a stack frame contains.

  • Function/Method Arguments: The values passed to the function/method.
  • Local Variables: Variables that are declared inside the function/method.
  • Return Address: The location in the code to return to after the function/method completes.


Let’s start the explanation with a code example.
public void Calculate()
{
    int a = 1;
    int b = 10;
    int c = a + b;

    Write(c);
    Console.WriteLine("Finished");
}

public void Write(int number)
{
    Console.WriteLine(number);
}


As you can see, there is a method named Calculate that declares 3 variables and is also called the Write method it.

Assume that, a thread calls the Calculate method, how would this be visualized?

As you can see from the image above, the first stack frame belongs to the Calculate method which stores 3 variables, one of which is the result of the sum of two variables. The second stack frame belongs to the Write method which stores the argument and return address (line 9 just for understanding, in fact, it contains different values).

So when the Write method completes the execution, the second stack frame is deallocated and the thread returns to the first stack frame that belongs to the Calculate method, through the return address it will execute from that address line and complete the execution of the Calculate method. In this way, the call stack loop that was called in this thread will continue to execute (in our case, execution is completed).

StackOverflowException

As I mentioned before, the stack size is limited, and for this reason, when any function/method is called in an unlimited and nested way, a “StackOverflowException” occurs.

Assume that we have some function/method that is using recursion but there is not any limitation. It means the method has some calculation in which there is no return state. So, in this case, we will get “StackOverFlowException”.

Let’s take a look at a code example.

public class Program
{
    public static void Main()
    {
        Calculate(2, 3);
    }

    public static void Calculate(int a, int b)
    {
        int c = a + b;
        Calculate(c, c * c);
    }
}


When you execute this code, you will get “StackOverFlowException” because recursion provides the call itself and there is no return state or limit in this function/method. With this technique, every call to the function/method creates new stack frames and when the stack limit is exceeded, we get a “StackOverFlowException”.

If you would like to learn more, stay tuned!



European ASP.NET Core 8.0.1 Hosting - HostForLIFE :: The Issue of Thread Synchronization and It's Resolution

clock May 14, 2024 06:53 by author Peter

Overview of synchronization issues

  • Assume that our shared count variable has a starting value of 0.
  • We wish to use this variable for two simultaneous activities.

Using Thread 1, add 1 to 100 to this variable.
Using Thread 2, subtract 1 to 100 from this value.

  • Print the variable's count at the end. It should ideally print 0. but it won't Because working on the same variable simultaneously by many threads can have unexpected outcomes.

When does the synchronization problem happen?
Critical Section
When more than one threads try to access the same code segment that segment is known as the critical section.
So, when more than one thread is there in the critical section at the same time, it can lead to unexpected results and synchronization problem.

Race Condition
If more than one thread tries to enter inside the critical section at the same time then it might lead to the synchronization problem.

Preemption
Preemption is the ability of the operating system to preempt(that is stop or pause) a currently scheduled task in favor of a higher priority task.
A program that is inside the critical section and CPU preempts then it can lead to the synchronization problem.

Solutions to the synchronization problem

In C#, there are several ways to synchronize access to shared resources to ensure thread safety and prevent race conditions.

Using lock keyword
The lock keyword provides a convenient way to create a synchronized block of code. It internally uses the Monitor class to achieve synchronization. The lock keyword ensures that only one thread can execute the locked code block at a time.

Example
private static object syncObject = new object();
private void Increment()
{
lock(syncObject)
{
    // Critical section: Access shared resource
}
}


Using Monitor Class
Instead of using the lock keyword, we can directly use methods of the Monitor class for synchronization.

Example
private static object syncObject = new object();
private void Increment()
{
Monitor.Enter(syncObject);
try
{
    // Critical section: Access shared resource
}
finally
{
    Monitor.Exit(syncObject);
}
}


Using Mutex
A mutex is a synchronization primitive that allows only one thread to acquire it at a time. It's typically used for inter-process synchronization to synchronize threads within the same process.

Example
private static Mutex mutex = new Mutex();
private void Increment()
{
mutex.WaitOne();
try
{
    // Critical section: Access shared resource
}
finally
{
    mutex.ReleaseMutex();
}
}

Using Semaphore
A semaphore is a synchronization primitive that allows a specified number of threads to enter a critical section simultaneously. It's useful when we want to limit the number of threads accessing a resource.

Example
private static Semaphore semaphore = new Semaphore(1, 1); // Limits access to one thread
private void Increment()
{
semaphore.WaitOne();
try
{
    // Critical section: Access shared resource
}
finally
{
    semaphore.Release();
}
}


Using Interlocked Class
The Interlocked class provides atomic operations for variables that are shared between threads. It's useful for performing simple operations like incrementing a counter without the need for locking.

Example
private int counter = 0;
public void Increment()
{
Interlocked.Increment(ref counter);
}

Properties of a good solution to the synchronization problem

Mutual Exclusion: Only one thread should be allowed inside the critical section at any point in time.
Progress: Overall system should keep on making progress. There shouldn't be a deadlock condition.
Bounded waiting: No thread should wait outside the critical section infinitely. There should be some bound on the waiting time.
No Busy Waiting: If a thread has to continuously check if they can enter inside the critical section or not is Busy Waiting.
    while(!allowed to enter critical section)

    {
        checking(); // <---- This is the busy waiting.
    }


There shouldn't be Busy waiting as it can have several consequences like

  • Inefficient use of CPU resources and wasted energy.
  • Reduced performance.
  • Increased power consumption.
  • Potential deadlocks and etc.



European ASP.NET Core 8.0.1 Hosting - HostForLIFE :: Comprehending.NET Core Garbage Collection

clock May 6, 2024 08:07 by author Peter

A key component of memory management in contemporary programming languages like C# is garbage collection (GC). The GC system is essential to.NET Core because it automatically recovers memory that is no longer in use, eliminating memory leaks and guaranteeing effective memory use. The purpose of this article is to examine the techniques and the parts that make up the garbage collection system in .NET Core.

Comprehending Trash Collection
Effective memory management is essential for developing strong applications, especially with C# and.NET Core. Garbage Collection (GC) is a key component of this ecosystem's automated memory management system, effectively managing memory deallocation and allocation. The process of automatically recovering memory used by objects that an application no longer needs is known as garbage collection. This is accomplished in.NET Core via a highly developed garbage collector that operates in the background, regularly searching the managed heap for things that have not been referenced and recovering their memory. Fundamentally, managed heap memory—the memory used by C# applications to store instantiated objects—is allocated and released by Garbage Collection in.NET Core.

Garbage Collection Components in.NET Core

  • Managed Heap: The managed heap is a section of memory set aside for the purpose of storing application-created objects by the Common Language Runtime (CLR). The managed heap in.NET Core is separated into three generations: Gen0, Gen1, and Gen2. Initially assigned to Gen0, objects are promoted to higher generations as long as they survive garbage collection cycles.
  • Garbage Collector: In.NET Core, the garbage collector is the main element in charge of memory reclamation. It runs in the background, periodically scanning the managed heap to locate and retrieve things that the application can no longer access. To maximize collection efficiency and reduce interference with application performance, the garbage collector employs a variety of algorithms and heuristics.
  • Finalization Queue: Finalization is supported by.NET Core, enabling objects to carry out cleanup operations prior to being picked up by garbage collectors. The finalization queue is a dedicated queue for objects that need to be finalized. In order to guarantee that their finalizers are called prior to their reclamation, objects in the finalization queue are handled independently during garbage collection.
  • Large Object Heap (LOH): In.NET Core, large objects (usually those greater than 85,000 bytes) are stored in the Large Object Heap, a separate section of the managed heap. Large items are treated differently by the trash collector due to their size in order to reduce fragmentation and enhance performance.

Three basic steps are involved in the operation of this automated process:

  • Marking: To determine which objects are still in use, the GC begins by iterating through all object references, beginning at the roots.
  • Relocating: The GC compacts the heap by moving active objects closer to one another after detecting them, improving speed and memory layout. It modifies references in parallel to take into account the updated memory addresses.
  • Clearing: The last phase involves the GC freeing up memory that has been occupied by objects that are no longer referenced, freeing up resources for new allocations.

Including Future Generations to Increase Efficiency
Generational memory management is one of the main techniques that.NET GC uses to increase efficiency. The managed heap is divided into three generations, each of which serves different object categories:

  • Gen 0: This segment accommodates short-lived objects, which typically have a transient lifespan within the application. As a result, a significant portion of memory reclamation occurs in this generation.
  • Gen 1: Positioned as a buffer between short-lived and long-lived objects, Generation 1 serves to segregate objects based on their longevity. Objects surviving multiple garbage collections in Gen 0 are promoted to Gen 1.
  • Gen 2: Comprising long-lived objects, Generation 2 hosts entities expected to persist throughout the application's lifecycle. Garbage collections within this segment are less frequent due to the enduring nature of its occupants.

Conclusion

Within the.NET Core ecosystem, garbage collection is a fundamental component of memory management because it provides an automated solution to the challenges associated with memory allocation and deallocation. Through an understanding of GC's inner workings and an embrace of generational memory management, developers may create apps that are more resilient to changing workloads and perform better overall. The finalization queue, managed heap, garbage collector, and other parts of.NET Core integrate flawlessly to automate memory management and offer a dependable execution environment for.NET Core programs.



European ASP.NET Core 8.0.1 Hosting - HostForLIFE :: Using.NET Aspire App to Deploy.NET 8 Core Web API in the Cloud

clock May 2, 2024 07:43 by author Peter

A cloud-ready, opinionated stack for developing distributed, observable, production-ready applications is.NET Aspire. Delivery of.NET Aspire occurs via a group of NuGet packages that address particular cloud-native issues. Microservices, which are tiny, interconnected units of code, are frequently used in place of a single, large code base in cloud-native applications. Typically, cloud-native applications use a lot of resources, including messaging, databases, and caching.

Overview
A cloud-ready toolset for creating contemporary distributed applications is called.NET Aspire. Its main goal is to assist developers in building observable, scalable microservices. .NET Aspire makes it easier to deploy.NET Core APIs and enables you to rapidly create cloud-native applications with a set of NuGet packages. Rather to having a single, massive code base, these applications usually comprise of smaller, connected components. For their operations to be successful in a cloud setting, they frequently depend on services like messaging, databases, and caching.

Starting a New Visual Studio 2022 Project
Starting a New Visual Studio 2022 Project An overview Launch the Visual Studio application, then choose "Create a new project."

The chosen application's project structure will be created by Visual Studio 2022. Since we're utilizing the ASP.Net Core Web API in this example, we can either utilize the pre-existing controller or construct a new one to write the code. You can enter the code there and use it to create or run the program.

To create a .NET Aspire Application, follow these steps.

  • Right-click on the Solution section in Visual Studio.
  • Select "Add" > "New Project."
  • Choose "Create a new project."
  • Find and select ".NET Aspire Application" from the list of project templates.

The .NET Aspire Application is a basic starter template that includes only the AppHost and ServiceDefaults projects. This template is designed to only provide the essentials for you to build off of

The .NET Aspire Application is a basic starter template that includes only the AppHost and ServiceDefaults projects. This template is designed to provide the essentials to build upon.

Project Structure

  • WEB: This is an ASP.NET Core API project, This project depends on the shared AspireCloud.ServiceDefaults project.
  • AspireCloud.AppHost: This is an orchestrator project designed to connect and configure the different projects and services of your app. This project handles running all of the projects that are part of the .NET Aspire application. The orchestrator should be set as the Startup project, and it depends on the WEBThis is the project responsible for running the applications inside of this solution.
  • AspireCloud.ServiceDefaults: This is a.NET Aspire shared project to manage configurations that are reused across the projects in your solution related to resilience, service discovery, and telemetry. This project ensures that all dependent services share the same resilience, service discovery, and OpenTelemetry configuration.

In the Program.cs file on the AppHost project, you can see the following code.
var builder = DistributedApplication.CreateBuilder(args);
var RESTAPI = builder.AddProject<Projects.WEB>("RESTAPI");
builder.Build().Run();

WEB .NET core API program.cs file configured in Aspire.ServiceDefaults.
builder.AddServiceDefaults();

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers();

// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle

builder.Services.AddEndpointsApiExplorer();

builder.Services.AddSwaggerGen();

//cloud configuration:

builder.AddServiceDefaults();

var app = builder.Build();

// Configure the HTTP request pipeline.

if (app.Environment.IsDevelopment())

{
    app.UseSwagger();

    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

On the Extensions. cs file, you can find some extension methods such as:

  • AddServiceDefaults: used to add default functionality.
  • ConfigureOpenTelemetry: used to configure OpenTelemetry metrics and tracing
  • AddDefaultHealthChecks: adds default health checks endpoints
  • MapDefaultEndpoints: maps the health check endpoint to /health and the liveness endpoint to alive.

Dashboard
Start the project with AspireCloud.AppHost is the Starter project (this project knows how to run the whole distributed application), and the following page will be opened in your browser with this nice dashboard.

In this dashboard, you can monitor various parts of your app, such as,

  • Projects: Displays information about your .NET projects in your .NET Aspire app, such as the app state, endpoints, and environment variables.
  • Containers: Displays information about your app containers, such as state, image tag, and port number (you should also see the Redis container you added for output caching with the name you provided.
  • Executables: Displays the running executables used by your app.
  • Logs: In this section, you can see the output logs for the projects, containers, and executables, and can also see the logs in a table format (structured).
  • Traces: displays the traces for your application, providing information about the requests.
  • Metrics: Displays various instruments and meters that are exposed and their corresponding dimensions for your app.

The Traces for your APIs.

 



European ASP.NET Core 8.0.1 Hosting - HostForLIFE :: Difference Between ReadOnly and Constant in .NET C#

clock April 29, 2024 09:48 by author Peter

Values that cannot be changed at runtime in C# are declared using the readonly and const keywords. However, there are several notable distinctions between these two words.

Constant: Describe It
Const is a compile-time constant, meaning that its value can only be set at compile time and cannot be modified by runtime. Usually, it is used for declaring global constants, such as mathematical constants or other values that aren't expected to change throughout program execution. Const values are intrinsically static and always belong to the class; they are not particular to any one instance of the class. Since they are by nature public, they can also be accessed from anywhere in the code.

public class Constants
{
  public const string CLIENT_ID = "ClientId";
}

ReadOnly:  What Is It?
Conversely, readonly fields are runtime constants, which means that only the class's constructor has the ability to modify them. Their value is predetermined at runtime. Since the readonly fields are instance-level variables, a duplicate of each field exists in each class instance. Additionally, they can be marked as static, indicating that they are part of the class itself rather than a specific class instance. You have to specifically declare the access level because the readonly fields are not inherently public.

public class TestService
{
  private readonly ISomeService _someService;

  public TestService(ISomeService someService)
  {
    _someService = someService;
  }
}


Key distinctions in C# between readonly and constant:
Constants in C# are defined using the readonly and const keywords, although their applications and capabilities differ.

When their values are set is one of the biggest distinctions between readonly and const. Values defined with the const keyword must be set at compile time and will not change at runtime. It implies that const values are decided upon during code compilation rather than execution. Conversely, readonly values are set at runtime and can only have their values assigned within the class constructor.

Const values are also fundamentally different since they are always implicitly static—that is, they are part of the class and not an instance of it. On the other hand, readonly values need to specifically state the access level and can be either instance-level or static.

The following example demonstrates the distinctions between readonly and const:
public class TestClass
{
    public const double PI = 3.14;
    public readonly string Name;

    public TestClass(string name)
    {
        Name = name;
    }
}


In this case, the const value PI was set to 3.14 at compile time. However, Name is a read-only variable that is set in the class's constructor and can only be changed during runtime.

The way that const and readonly are accessible is another distinction between them. Readonly values require the access level to be explicitly specified, whereas const variables are always implicitly public.

While read-only variables are determined at runtime, const values are computed at compile time.
While read-only fields might be instance-level or static and require the access level to be explicitly specified, const values are always static and automatically public.

Readonly fields can only be modified within the class constructor, but const values cannot be altered at runtime.

ReadOnly vs Constant

ReadOnly keyword Const keyword
The readonly keyword in C# can be used to create readonly fields. The const keyword in C# is used to construct constant fields.
The runtime constant ReadOnly. A compile-time constant is called const.
It is possible to modify the readonly field's value. It is not possible to modify the value of the const field.
It can't be declared within the procedure. It may be specified within the procedure.
We can set values in the constructor and declaration sections of read-only fields. We can only assign values to the declaration part of const fields.
The use of static modifiers is possible. Static modifiers are incompatible with its use.

When should you use CONSTANTS versus READONLY?

Utilize constants when the values are absolute, fixed, and do not vary, such as DaysOfWeek, MonthsOfYear, mathematical PI value, and so on. Use readonly when the variables are obtained via user input, configuration files, or any other variable that does not have the same value, such as a database connection string, a secret key, and so on.

We learned the new technique and evolved together.



European ASP.NET Core 8.0.1 Hosting - HostForLIFE :: Extracting Values from PDFs in .NET Core 8 without ASP.NET

clock April 22, 2024 08:38 by author Peter

Within software development, data extraction from PDF files is frequently required for a number of activities, including content indexing, information retrieval, and data analysis. Although ASP.NET Core 8 provides powerful tools for working with PDFs, there are times when developers would rather have other options due to project needs or flexibility concerns. In this post, we'll look at how to use the PdfSharpCore library to extract values from PDF files inside the.NET Core 8 environment without utilizing ASP.NET. We'll present you a detailed how-to and C# examples to show you how to complete this task successfully.

  • Comprehending PdfSharpCore: PdfSharpCore is a well-liked.NET library designed for manipulating PDF documents. It offers tools for adding, editing, and removing material from PDF files. This tutorial will concentrate on using PdfSharpCore to extract text from PDF files.
  • Installing PdfSharpCore: Installing the PdfSharpCore NuGet package is necessary before we can use PdfSharpCore in our.NET Core application. The.NET CLI or the NuGet Package Manager Console can be used for this.

Using the NuGet Package Manager Console
Install-Package PdfSharpCore

Using the .NET CLI
dotnet add package PdfSharpCore

Extracting Text from PDFs in C#: Now that we have PdfSharpCore installed, let's dive into how we can extract text from PDF files using C#.
using PdfSharpCore.Pdf;
using PdfSharpCore.Pdf.IO;
using System;

public class PdfTextExtractor
{
    public static string ExtractTextFromPdf(string filePath)
    {
        using (PdfDocument document = PdfReader.Open(filePath, PdfDocumentOpenMode.Import))
        {
            string text = "";
            foreach (PdfPage page in document.Pages)
            {
                text += page.GetText();
            }
            return text;
        }
    }

    // Example usage:
    public static void Main(string[] args)
    {
        string pdfText = ExtractTextFromPdf("sample.pdf");
        Console.WriteLine(pdfText);
    }
}

The extracted text is returned by the static method ExtractTextFromPdf, which we have implemented in this example. It accepts the file path of the PDF as input and returns the retrieved text. Within the procedure, we access the PDF file using PdfSharpCore, loop through its pages, and extract text from each one. The extracted text is then concatenated and sent back.

Conclusion
By leveraging PdfSharpCore in .NET Core 8, developers have access to a powerful and efficient tool for extracting text from PDF files. Without relying on ASP.NET, PdfSharpCore provides a straightforward solution for handling PDF documents within the .NET Core ecosystem. Whether you're building data processing pipelines, content management systems, or document parsing utilities, PdfSharpCore empowers developers to accomplish PDF manipulation tasks effectively and seamlessly.



European ASP.NET Core 8.0.1 Hosting - HostForLIFE :: C# &.NET: Experimental Attribute

clock April 16, 2024 08:45 by author Peter

You can add the Experimental property to your types, methods, or assemblies to designate that a feature is experimental using the new Experimental attribute in C# 12. When someone tries to use the method or the type after you've done this, the compiler will throw an error. I describe how to use this functionality in this article.


I used Visual Studio 2022 Preview to construct a console application with.NET 8 and run it for demonstration purposes. Use of the Preview version is required until the article's date. This feature will not function otherwise.

The System.Diagnostics.CodeAnalysis namespace is where the Experimental attribute originates. You can see an example of a class with this attribute in the code below:

using System.Diagnostics.CodeAnalysis;

namespace DotNet8Examples
{
    [Experimental(diagnosticId: "Test001")]
    public class ExperimentalAttributeDemo
    {
        public void Print()
        {
            Console.WriteLine("Hello Experimental Attribute");
        }
    }
}


On line 1, there is the namespace for the Experimental attribute.
On line 5, there is the Experimental attribute, with the diagnosticId. For the diagnosticId, you can specify an Id, which will be used by the compiler, to report a usage of the API the attribute applies to.
On line 8, there is a method for this class.

Now, if you try to create an instance of this class, the compiler will complain about it:
var experimentalAttributeDemo = new ExperimentalAttributeDemo();

It should be noted that the Experimental property can be used in both the method and the class. You can use the NoWarn property in the.csproj file to use this class and ignore this error; this will work on a global level, so each time you try to use the class or method, you won't have to suppress the error; alternatively, you can suppress it directly on the code, which will require you to do so each time you need to use the class or method.

I'm directly suppressing the error Test001 in the code in the example below. In order to do it, you must add your code in between the #pragma warning disable Test001 and the #pragma warning restore Test001:



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