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 10.0 Hosting - HostForLIFE :: Evaluating .NET 11's Native AOT Performance

clock September 21, 2026 12:52 by author Peter

Historically, managed code execution in.NET applications has relied on the JIT compiler and the.NET runtime. Although there are other deployment options available, this strategy is effective for a variety of applications.

A distinct strategy is used in native AOT (Ahead-of-Time) compilation. The program is compiled in advance into native code for the target platform rather than depending on JIT compilation when it launches. This can alter an application's memory utilization, deployment requirements, starting behavior, and compatibility with specific.NET technologies, among other aspects.

For applications like command-line tools, tiny services, containerized apps, and workloads where startup time is crucial, native AOT is especially intriguing.

But not all applications immediately benefit from native AOT's speed.

The right way to evaluate it is to build the same application using both deployment models and measure the things that matter for your workload.

This article explains how Native AOT works, how to enable it, what to benchmark, and what limitations developers should consider.

What Is Native AOT?

With a traditional .NET deployment, the application contains managed assemblies.

A simplified execution flow looks like this:
C# Source
    |
    v
IL Assemblies
    |
    v
.NET Runtime
    |
    v
JIT
    |
    v
Native Machine Code


Native AOT changes the model:
C# Source
    |
    v
IL Assemblies
    |
    v
Native AOT Compiler
    |
    v
Native Executable
    |
    v
Operating System


Much of the compilation work happens before the application is deployed. The resulting executable is native code for a specific target platform and architecture.

This means Native AOT is not simply a switch that makes a normal .NET application run faster.

It changes the deployment and execution model.

Why Developers Use Native AOT

Native AOT can be useful when an application needs characteristics such as:

  • Fast startup
  • Smaller runtime dependency requirements
  • Self-contained native deployment
  • Reduced JIT work at startup
  • Predictable deployment artifacts
  • Useful behavior for short-lived processes

Consider a command-line utility:
mytool --input data.json

If the tool runs for a few hundred milliseconds, startup overhead can represent a meaningful part of its total execution time.
For a long-running web service that runs continuously for days, startup may matter much less.

This is why workload type is important.

Native AOT vs JIT Deployment

The two approaches have different characteristics.

Area

Traditional JIT

Native AOT

Compilation

At runtime

Before deployment

Startup work

Includes JIT work

Less JIT work

Target-specific binary

Runtime generates code for target

Native binary built for target

Dynamic code

Broad support

More restricted

Reflection

Broad support

Requires additional consideration

Deployment

Managed assemblies and runtime

Native executable

Build process

Generally simpler

More involved

Best fit

General-purpose applications

Suitable workloads with AOT-compatible dependencies

Native AOT is therefore a deployment choice, not simply a performance setting.

Enabling Native AOT
For a suitable .NET application, Native AOT can be enabled in the project file.

For example:
<PropertyGroup>
  <OutputType>Exe</OutputType>
  <TargetFramework>net11.0</TargetFramework>
  <PublishAot>true</PublishAot>
</PropertyGroup>

You can then publish the application for a target runtime.

For example:
dotnet publish -c Release -r linux-x64

The runtime identifier should match the environment where the application will run.

For an Arm64 Linux environment, the target would need to be the appropriate Arm64 runtime identifier instead.

The important point is that Native AOT produces a native binary for a specific target.

A Simple Console Application


Start with a small application:
using System.Diagnostics;

Console.WriteLine("Application started.");

var stopwatch = Stopwatch.StartNew();

long total = 0;

for (int i = 0; i < 10_000_000; i++)
{
    total += i;
}

stopwatch.Stop();

Console.WriteLine($"Total: {total}");
Console.WriteLine($"Work time: {stopwatch.ElapsedMilliseconds} ms");


This is useful for experimenting, but it is not enough to conclude that Native AOT is faster.

The test only measures one small piece of work.

A useful evaluation needs to measure startup, execution, memory, and deployment characteristics separately.
Startup Time

Startup is one of the areas where Native AOT can be particularly relevant.

A traditional application may perform several runtime initialization tasks before reaching the main application code.

A Native AOT application has already been compiled to native code.

To test startup, run the application as a separate process and measure the time from process launch to a known output or completion point.

Avoid using:

Stopwatch.StartNew();

inside the application to measure total startup.

That stopwatch starts after the process has already started.

Instead, use an external measurement mechanism or a suitable benchmarking tool.

For example, on Linux, a basic shell-level measurement can be used:

time ./myapp

This provides process-level timing information.

Repeat the test multiple times and compare the same application under both deployment models.
Cold Start vs Warm Start

Startup tests should distinguish between different conditions.
Cold Start

The application is started when relevant code and files are not already benefiting from the operating system's caches.
Warm Start

The application is launched after the operating system has already cached relevant files.

These scenarios can produce different results.

For applications such as serverless functions and short-lived CLI tools, cold-start behavior may be particularly important.

For long-running services, startup may have a much smaller impact on overall performance.
Measuring Memory Usage

Memory usage is another important measurement.

Do not simply compare executable file sizes and assume that the smaller file consumes less memory at runtime.

Measure the running process.

A practical test should record:

    Initial memory

    Steady-state memory

    Peak memory

    Allocation behavior

    Garbage collection activity

For a long-running service, steady-state behavior may matter more than startup memory.

For a short-lived process, startup and peak memory can be more relevant.
Throughput Testing

Native AOT should also be tested against the actual workload.

For example, imagine a service processing messages:

public static int Process(int value)
{
    return value * 2;
}

A benchmark might process many values:

public static long ProcessValues(int[] values)
{
    long total = 0;

    for (int i = 0; i < values.Length; i++)
    {
        total += Process(values[i]);
    }

    return total;
}

Now compare the same application deployed using normal JIT execution and Native AOT.

The important question is not whether one test is faster.

The question is whether the difference remains meaningful under the application's real workload.
Native AOT Does Not Mean No Runtime

Native AOT applications are native executables, but they still rely on runtime support and libraries.

The important distinction is that application code is compiled ahead of time instead of being JIT-compiled in the normal way at runtime.

Native AOT also has a different set of supported features and restrictions.

This is particularly important for applications that depend heavily on runtime code generation or unrestricted reflection.
Reflection Requires Attention

Reflection is widely used in .NET applications.

For example:

Type type = typeof(Customer);

PropertyInfo[] properties =
    type.GetProperties();

Applications that dynamically discover types, members, or assemblies may require additional work when using Native AOT.

Native AOT relies heavily on knowing what code is required at build time.

If the compiler cannot determine that a type or member is required, the application may need appropriate metadata or code annotations.

This is one of the biggest areas to investigate before migrating an existing application.
Dynamic Code Can Be a Problem

Some libraries generate code dynamically at runtime.

Examples can include:

  • Runtime proxies
  • Dynamic serializers
  • Expression compilation
  • Runtime assembly generation
  • Certain reflection-heavy frameworks

An application may work correctly under the normal JIT deployment model and then require changes for Native AOT.

This is why compatibility testing should happen before performance testing.

There is no value in benchmarking an AOT build that cannot correctly execute the application's actual features.

A Practical Testing Process

A reliable Native AOT evaluation can follow these steps.

Step 1: Choose a Representative Application
Do not start with a toy application unless you are learning how the technology works.
For a real migration decision, use a representative service or tool.

Step 2: Build the Normal Version
Publish the application using the normal deployment model.

For example:
dotnet publish -c Release

Step 3: Enable Native AOT
Add the appropriate project configuration:
<PropertyGroup>
  <PublishAot>true</PublishAot>
</PropertyGroup>

Then publish for the target platform:
dotnet publish -c Release -r linux-x64

Step 4: Verify Functionality
Before measuring performance, verify:

  • Application startup
  • API behavior
  • Serialization
  • Configuration
  • Logging
  • Database access
  • Authentication
  • Error handling
  • External integrations

Step 5: Measure Startup
Run the same executable repeatedly and record startup behavior.

Step 6: Measure Memory
Measure both startup and steady-state memory.

Step 7: Measure Throughput
Run realistic workloads against both versions.

Step 8: Compare Results

se the same hardware, operating system, configuration, and input data.

Benchmarking Application Code
For CPU-focused comparisons, BenchmarkDotNet can be useful.

For example:
using BenchmarkDotNet.Attributes;

public class ProcessingBenchmark
{
    private readonly int[] values = new int[100_000];

    [Benchmark]
    public long Process()
    {
        long total = 0;

        for (int i = 0; i < values.Length; i++)
        {
            total += values[i] * 2;
        }

        return total;
    }
}

This measures application code rather than complete process startup.
That distinction matters.

Use process-level measurements for startup and application-level benchmarks for CPU operations.
Do not use one benchmark to answer every performance question.

What Should You Measure?

A useful comparison might look like this:

Metric

Why it matters

Startup time

Important for short-lived processes

First request latency

Useful for services

Steady-state latency

Shows normal runtime behavior

Throughput

Shows processing capacity

Peak memory

Important for constrained environments

Steady-state memory

Useful for long-running services

CPU usage

Helps identify processing differences

Binary size

Important for deployment and distribution

Build time

AOT can increase build complexity

Compatibility

Required before performance comparisons

This gives a much more complete picture than simply comparing execution time.

Common Mistakes
Comparing Debug Builds
Always use the appropriate Release configuration when performing performance testing.
dotnet publish -c Release

Testing Different Hardware
If the JIT version runs on one server and the AOT version runs on another, the comparison is difficult to interpret.

Use the same environment where possible.

Measuring Only Startup

Native AOT can change startup characteristics, but that does not tell you how the application behaves after it has been running for hours.

Measuring Only CPU Time

A service may have excellent CPU performance but still have a memory or I/O bottleneck.

Ignoring Compatibility
An application that cannot use an important dependency under AOT is not a successful AOT candidate regardless of benchmark results.

Best Practices
Keep a Baseline

Before changing the deployment model, record the existing application's performance.

Use Production-Like Workloads

If production processes JSON requests, test JSON requests.

If production processes files, test representative files.

Test on the Target Architecture

An AOT binary is built for a specific target environment.

Test it where it will actually run.

Separate Startup and Steady-State Tests
Do not mix the two measurements.

Test Multiple Runs
One run can be affected by system activity and caching.

Use repeated measurements and look for consistent results.

Check Dependencies Early
Review the libraries used by the application before committing to an AOT migration.

Monitor Real Applications
If the application is deployed, continue measuring real behavior after the change.

Advantages of Native AOT

Native AOT can provide several practical benefits for suitable applications:

  • Less JIT work at startup
  • Native executable deployment
  • Potentially useful startup characteristics
  • Reduced dependency on runtime compilation
  • Useful fit for certain short-lived workloads
  • Can simplify deployment for some environments

The actual benefit depends on the application.

Disadvantages and Trade-Offs
Native AOT also introduces trade-offs:

  • Some .NET features require additional consideration
  • Reflection-heavy applications may need changes
  • Some libraries may not be AOT-compatible
  • Builds can become more involved
  • Native binaries are target-specific
  • Debugging and diagnostics can differ from a normal managed deployment
  • Dynamic code generation has restrictions

These are not reasons to avoid Native AOT.

They are reasons to evaluate it against the actual application.

When Native AOT Is Worth Testing
Native AOT is particularly worth evaluating for:

  • Command-line tools
  • Short-lived workers
  • Small services
  • Container workloads
  • Applications where startup matters
  • Resource-constrained environments

It may be less compelling when:

  • The application runs continuously for long periods.
  • Startup time is insignificant.
  • The application relies heavily on dynamic runtime behavior.
  • Dependencies are not compatible with AOT.
  • The main bottleneck is database or network I/O.

Again, these are starting points rather than universal rules.

Troubleshooting Native AOT Builds

If publishing fails, start by examining the build output.

Common areas to investigate include:

Reflection

Look for code that discovers types or members dynamically.

Dynamic Code Generation
Check whether a dependency requires runtime-generated code.

Serialization

Verify that the serializer and configuration are compatible with the AOT deployment model.

Dependencies

A library used by the application may have AOT limitations.

Platform Target
Make sure the runtime identifier matches the actual deployment environment.

For example:
dotnet publish -c Release -r linux-x64

should not be used to produce the binary intended for a different architecture.

A Simple Evaluation Matrix
Before adopting Native AOT, document the results.

Test

JIT Deployment

Native AOT

Observation

Startup

Measure

Measure

Compare repeated runs

First request

Measure

Measure

Use same request

Throughput

Measure

Measure

Same workload

Peak memory

Measure

Measure

Same environment

Steady-state memory

Measure

Measure

Long-running test

CPU usage

Measure

Measure

Same workload

Build time

Measure

Measure

Include CI build

Compatibility

Verify

Verify

All required features

The purpose of this table is not to produce a single winner.

It gives the team enough information to decide whether the deployment model fits the application's requirements.

Summary
Native AOT changes how a .NET application is compiled and deployed. Instead of depending on normal JIT compilation for application code at runtime, the application is compiled ahead of time into a native executable for a specific target environment.

The most useful way to evaluate Native AOT is through measurement. Test startup time, first-request behavior, steady-state performance, memory usage, CPU usage, binary size, build time, and application compatibility.

Native AOT can be a good fit for applications where startup and deployment characteristics matter, but it is not a universal performance switch. Applications that rely heavily on reflection, dynamic code generation, or incompatible dependencies may require additional changes.

For developers considering Native AOT, the safest approach is to establish a baseline, build an AOT version, verify that all required functionality still works, and then compare both versions using the same hardware and realistic workloads. That gives you evidence about whether Native AOT is useful for your application instead of relying on a generic performance claim.

HostForLIFE.eu ASP.NET Core 10.0 Hosting
European best, cheap and reliable ASP.NET hosting with instant activation. HostForLIFE.eu is #1 Recommended Windows and ASP.NET hosting in European Continent. With 99.99% Uptime Guaranteed of Relibility, Stability and Performace. HostForLIFE.eu security team is constantly monitoring the entire network for unusual behaviour. We deliver hosting solution including Shared hosting, Cloud hosting, Reseller hosting, Dedicated Servers, and IT as Service for companies of all size.



European ASP.NET Core 10.0 Hosting - HostForLIFE :: The Complete Guide to ASP.NET Core Observability and Resilience

clock June 15, 2026 07:09 by author Peter

Developing a local application is just the first step. What occurs in production is the real litmus test for software engineering. How fast can you identify the underlying problem when a null reference exception ends a user session, a third-party API rate-limits your server, or a database query hangs?

Diagnosing problems in a distributed system is like trying to identify a needle in a haystack if you rely on simple text files and dispersed try/catch sections. Three pillars must be mastered in order to create an enterprise-grade ASP.NET Core application that is really resilient: Centralized Log Aggregation, the Middleware Pipeline, and Structured Logging. Let's investigate how to put this architecture into practice.

Phase 1: The Foundation for Observability (Structured Logging)
Treating logging as a means of writing text to a console is the most common error made by developers.
The String Interpolation Anti-Pattern:

_logger.LogInformation($"User {userId} successfully authenticated at {DateTime.Now}");

This generates a flat string. When you have millions of logs, you cannot easily query your database for "all logs where the UserId was 123".

The Best Practice (Structured Logging):
_logger.LogInformation("User {UserId} successfully authenticated.", userId);

By using message templates ({UserId}), ASP.NET Core preserves the property names and their values. Your logging provider stores UserId as an indexed, queryable column.
Applying Structured Logging Layer-by-Layer

To make an application truly observable, logging must be treated as a first-class citizen across all layers:

  • Controllers (The Entry Point): Log who is making the request and what the outcome is. If an Admin locks a user's account, capture the Admin's ID, not just the target user's ID, to create a secure audit trail.
  • Services (The Business Logic): Log the intent and outcome of external integrations. When calling third-party gateways, catch specific exceptions (like HttpRequestException) and log them, so you don't mistake a firewall block for a bug in your own code. Never log secrets, API keys, or passwords.
  • Repositories (The Database Frontier): Log the execution of queries. During logging audits, you will often find performance anti-patterns. For example, replacing a synchronous .FirstOrDefault() with an asynchronous .FirstOrDefaultAsync() prevents catastrophic thread-pool starvation under heavy load. Always log the Exception object in your catch blocks so stack traces aren't swallowed.

Phase 2: Mastering the Control Flow (Middleware)
Before an HTTP request ever reaches your Controller, it travels through the Middleware Pipeline. Think of middleware like a series of water filters. Each component can examine the request, modify it, pass it to the next component, or "short-circuit" and immediately return a response.

Because each middleware wraps the next one, the order in which you register them in Program.cs is critical.

Global Exception Handling (Must be first to catch errors from everything below it)

  • HTTPS Redirection & Static Files
  • Routing (Figure out where the request is going)
  • Authentication (Who are you?)
  • Authorization (Are you allowed to be here?)
  • Custom Middleware (e.g., API Key Validation)
  • Controllers / Endpoints


Phase 3: The Ultimate Safety Net (Global Exception Handling)
Sprinkling try/catch blocks inside every single Controller action makes your code messy and prone to data leakage. Instead, we use the Middleware Pipeline to build a Global Exception Handler.

By placing this middleware at the absolute top of the pipeline, it wraps the entire application in a try/catch. If any code throws an unhandled exception, it bubbles up to this middleware, which logs the exact error and returns a clean, standardized JSON response to the client—without leaking sensitive stack traces.
public class GlobalExceptionMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger<GlobalExceptionMiddleware> _logger;

    public GlobalExceptionMiddleware(RequestDelegate next, ILogger<GlobalExceptionMiddleware> logger)
    {
        _next = next;
        _logger = logger;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        try
        {
            await _next(context); // Pass request down the pipeline
        }
        catch (Exception ex)
        {
            // The request blew up somewhere, and the error bubbled back up to here!
            context.Response.ContentType = "application/json";
            context.Response.StatusCode = 500; // Default to Internal Server Error

            // Map specific exceptions to HTTP Status Codes
            if (ex is UnauthorizedAccessException) context.Response.StatusCode = 401;
            if (ex is KeyNotFoundException) context.Response.StatusCode = 404;

            // Log the structured error
            _logger.LogError(ex, "Unhandled exception on {RequestPath}. Method: {RequestMethod}", context.Request.Path, context.Request.Method);

            // Return a safe, standard JSON response
            var errorResponse = JsonSerializer.Serialize(new {
                Status = context.Response.StatusCode,
                Message = "An unexpected error occurred."
            });
            await context.Response.WriteAsync(errorResponse);
        }
    }
}


To see exactly how a request flows through the pipeline and how exceptions bubble up to be caught by this middleware, you can run the interactive simulation below.

Phase 4: The Centralized Brain (Serilog)
Now that your application is emitting beautiful structured logs and gracefully catching every exception, you need a place to view them. Local text files are useless in a multi-server production environment.

We integrate Serilog to aggregate these logs and ship them to a centralized platform (like Seq, Datadog, or Elasticsearch). Because we used standard ILogger everywhere, we don't need to change our business logic; we just wire Serilog into Program.cs using the Two-Stage Initialization pattern.

  • Install Packages: Serilog.AspNetCore, Serilog.Sinks.Console, Serilog.Sinks.Seq (or File).
  • Configure appsettings.json: Define your log levels and routing destinations without hardcoding them.
  • Bootstrap in Program.cs: Catch startup errors and replace noisy default HTTP logging with clean, single-line logs.

using Serilog;
// 1. Catch startup errors before the app even builds
Log.Logger = new LoggerConfiguration().WriteTo.Console().CreateBootstrapLogger();

try
{
    var builder = WebApplication.CreateBuilder(args);

    // 2. Wire Serilog into the ASP.NET Core host
    builder.Host.UseSerilog((context, services, configuration) => configuration
        .ReadFrom.Configuration(context.Configuration)
        .Enrich.FromLogContext());

    var app = builder.Build();

    // 3. Register our safety net FIRST
    app.UseMiddleware<GlobalExceptionMiddleware>();

    // 4. Clean, single-line HTTP Request Logging
    app.UseSerilogRequestLogging();

    app.UseRouting();
    app.MapControllers();
    app.Run();
}
catch (Exception ex)
{
    Log.Fatal(ex, "Host terminated unexpectedly");
}
finally
{
    Log.CloseAndFlush();
}


Conclusion

You can turn your application from a brittle black box into a highly observable, robust enterprise system by integrating Structured Logging, a thorough grasp of the Middleware Pipeline, a Global Exception Handler, and Serilog. You won't be speculating when the unavoidable production problem arises. Your consolidated dashboard will receive precise, queryable context, enabling you to find and fix the underlying issue in a matter of minutes.

HostForLIFE.eu ASP.NET Core 10.0 Hosting
European best, cheap and reliable ASP.NET hosting with instant activation. HostForLIFE.eu is #1 Recommended Windows and ASP.NET hosting in European Continent. With 99.99% Uptime Guaranteed of Relibility, Stability and Performace. HostForLIFE.eu security team is constantly monitoring the entire network for unusual behaviour. We deliver hosting solution including Shared hosting, Cloud hosting, Reseller hosting, Dedicated Servers, and IT as Service for companies of all size.



European ASP.NET Core 10.0 Hosting - HostForLIFE ::Overview of ASP.NET Core Web API JSON Serialization

clock May 4, 2026 09:06 by author Peter

The process of transforming C# objects into JSON strings (for responses) and back again (for request bodies) is known as JSON serialization in ASP.NET Core Web API. Although ASP.NET Core takes care of this automatically by default, creating professional APIs requires knowing how to customize it.

[HttpGet]
public IActionResult GetUser()
{
    var user = new User { Id = 1, Name = "Alice" };
    return Ok(user); // Automatically serialized to {"id": 1, "name": "Alice"}
}


2. Configuration & Global Settings
You can customize serialization behavior globally in your Program.cs. Common tasks include enabling "pretty printing" (indentation) or changing how property names are cased.

builder.Services.AddControllers()
    .AddJsonOptions(options =>
    {
        // 1. Indent the JSON for readability
        options.JsonSerializerOptions.WriteIndented = true;

        // 2. Ignore properties that are null
        options.JsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;

        // 3. Keep property names as they are in C# (PascalCase) instead of camelCase
        options.JsonSerializerOptions.PropertyNamingPolicy = null;
    });


3. Using Attributes for Fine Control

Sometimes you only want to change serialization for a specific class or property. You can use attributes directly on your models:

Attribute Purpose
[JsonPropertyName("user_id")] Renames the property in the JSON output.
[JsonIgnore] Prevents the property from being serialized at all.
[JsonInclude] Forces a private property to be included.
[JsonConstructor] Tells the serializer which constructor to use for deserialization.

Example:

public class Product
{
    [JsonPropertyName("sku_code")]
    public string Sku { get; set; }

    [JsonIgnore]
    public decimal InternalCost { get; set; }
}


4. System.Text.Json vs. Newtonsoft. Json

While System.Text.Json is the default, many legacy or complex projects still use Newtonsoft.Json (Json.NET).

Feature System.Text.Json (Default) Newtonsoft.Json (Json.NET)
Performance Faster, uses less memory. Slower due to heavy reflection.
Compatibility Built into .NET. Requires a NuGet package.
Features Strict, standard-compliant. Highly flexible, handles edge cases easily.
Native AOT Fully supported (via Source Gen). Not supported.

How to switch to Newtonsoft.Json:
If you need specific features like JsonPatch or complex reference handling, install the Microsoft.AspNetCore.Mvc.NewtonsoftJson package and update Program.cs:
builder.Services.AddControllers().AddNewtonsoftJson();

5. Best Practices for 2026
Stick to System.Text.Json: Unless you have a specific technical debt reason to use Newtonsoft, the performance gains and security of the built-in library are worth it.
Use Source Generation: For high-traffic APIs or Cloud Native/Native AOT apps, use JSON Source Generators to eliminate reflection at runtime.
Avoid Circular References: If your models reference each other (e.g., Parent → Child → Parent), use ReferenceHandler.IgnoreCycles to prevent the serializer from crashing.
Contracts First: Always define DTOs (Data Transfer Objects) specifically for your API rather than serializing your Database Entities directly.

Are you looking to migrate an existing project from Newtonsoft.Json, or are you starting a fresh project from scratch?



European ASP.NET Core 10.0 Hosting - HostForLIFE :: Customizing Word Document Headers and Footers using C#

clock April 20, 2026 09:43 by author Peter

In Word documents, headers and footers are crucial components that show consistent information at the top or bottom of each page, including page numbers, document titles, and company names. Manual processes can be ineffective when handling big document quantities or inserting headers and footers in batches. Using C# to automate these tasks can significantly improve document processing efficiency.

This article shows how to use C# and the Spire to create and modify headers and footers in Word documents.Common functions like adding text, graphics, and page numbers, as well as creating distinct headers and footers for odd and even pages, are covered by the Doc library.

Environment Setup
First, install the Spire.Doc package via NuGet:
Install-Package Spire.Doc

Or using the .NET CLI:
dotnet add package Spire.Doc

After installation, add the following namespaces to your C# code:
using Spire.Doc;
using Spire.Doc.Documents;
using Spire.Doc.Fields;
using System.Drawing;

Basic Concepts
Before writing code, it's important to understand several key concepts:

  • Section: A Word document consists of one or more sections, each with its own header and footer settings
  • Header: The area located at the top of the page
  • Footer: The area located at the bottom of the page
  • Paragraph: Content in headers and footers is organized and displayed through paragraphs

Adding Basic Headers and Footers
The following example demonstrates how to add headers and footers containing text and images to a Word document:
using Spire.Doc;
using Spire.Doc.Documents;
using Spire.Doc.Fields;
using System.Drawing;

// Create a document object and load the file
Document document = new Document();
document.LoadFromFile("Sample.docx");

// Get the first section
Section section = document.Sections[0];

// Get header and footer objects
HeaderFooter header = section.HeadersFooters.Header;
HeaderFooter footer = section.HeadersFooters.Footer;

// Add a paragraph to the header
Paragraph headerParagraph = header.AddParagraph();

// Add an image to the header
DocPicture headerPicture = headerParagraph.AppendPicture(Image.FromFile("Header.png"));

// Set image size and position
headerPicture.Width = 40;
headerPicture.Height = 40;
headerPicture.TextWrappingStyle = TextWrappingStyle.InFrontOfText;
headerPicture.HorizontalAlignment = ShapeHorizontalAlignment.Left;
headerPicture.VerticalAlignment = ShapeVerticalAlignment.Outside;

// Add text to the header
TextRange text = headerParagraph.AppendText("Internal Company Document");
text.CharacterFormat.FontName = "Arial";
text.CharacterFormat.FontSize = 10;
text.CharacterFormat.Italic = true;

// Set header paragraph right alignment
headerParagraph.Format.HorizontalAlignment = HorizontalAlignment.Right;

// Add bottom border line
headerParagraph.Format.Borders.Bottom.BorderType = BorderStyle.Single;
headerParagraph.Format.Borders.Bottom.Space = 0.05f;

// Add a paragraph to the footer
Paragraph footerParagraph = footer.AddParagraph();

// Add page number field
footerParagraph.AppendField("page number", FieldType.FieldPage);
footerParagraph.AppendText(" / ");
footerParagraph.AppendField("number of pages", FieldType.FieldNumPages);

// Set footer paragraph center alignment
footerParagraph.Format.HorizontalAlignment = HorizontalAlignment.Center;

// Save the document
document.SaveToFile("HeaderAndFooter.docx", FileFormat.Docx);
document.Dispose();

Below is the generated document's header and footer:

This code first loads an existing Word document, then retrieves the first section. The header and footer objects are accessed through the HeadersFooters property, paragraphs are added using the AddParagraph() method, and images and text content are added via the AppendPicture() and AppendText() methods.

Setting Different Headers and Footers for Odd and Even Pages

In formal documents, it's often necessary to set different headers and footers for odd and even pages. For example, odd pages may display chapter titles while even pages display the document name. The following code demonstrates how to implement this functionality:

using Spire.Doc;
using Spire.Doc.Documents;
using Spire.Doc.Fields;

// Load the document
Document doc = new Document();
doc.LoadFromFile("MultiplePages.docx");

// Get the first section
Section section = doc.Sections[0];

// Enable different headers and footers for odd and even pages
section.PageSetup.DifferentOddAndEvenPagesHeaderFooter = true;

// Add odd page header
Paragraph oddHeaderPara = section.HeadersFooters.OddHeader.AddParagraph();
TextRange oddHeaderText = oddHeaderPara.AppendText("Odd Page Header - Chapter Title");
oddHeaderPara.Format.HorizontalAlignment = HorizontalAlignment.Center;
oddHeaderText.CharacterFormat.FontName = "Arial";
oddHeaderText.CharacterFormat.FontSize = 10;

// Add even page header
Paragraph evenHeaderPara = section.HeadersFooters.EvenHeader.AddParagraph();
TextRange evenHeaderText = evenHeaderPara.AppendText("Even Page Header - Document Name");
evenHeaderPara.Format.HorizontalAlignment = HorizontalAlignment.Center;
evenHeaderText.CharacterFormat.FontName = "Arial";
evenHeaderText.CharacterFormat.FontSize = 10;

// Add odd page footer
Paragraph oddFooterPara = section.HeadersFooters.OddFooter.AddParagraph();
TextRange oddFooterText = oddFooterPara.AppendText("Odd Page Footer");
oddFooterPara.Format.HorizontalAlignment = HorizontalAlignment.Center;

// Add even page footer
Paragraph evenFooterPara = section.HeadersFooters.EvenFooter.AddParagraph();
TextRange evenFooterText = evenFooterPara.AppendText("Even Page Footer");
evenFooterPara.Format.HorizontalAlignment = HorizontalAlignment.Center;

// Save the document
doc.SaveToFile("OddAndEvenHeaderFooter.docx", FileFormat.Docx);
doc.Dispose();


The generated document's header and footer are shown below:

Setting the DifferentOddAndEvenPagesHeaderFooter property to true is crucial. Next, use the OddHeader, EvenHeader, OddFooter, and EvenFooter properties to access and modify the headers and footers for odd and even pages independently.

Changing the Header and Footer of the First Page
Certain papers call for either no headers and footers on the first page or specific headers and footers. This can be accomplished in the manner described below:

using Spire.Doc;
using Spire.Doc.Documents;
using Spire.Doc.Fields;

// Load the document
Document doc = new Document();
doc.LoadFromFile("Sample.docx");

// Get the first section
Section section = doc.Sections[0];

// Enable different first page header and footer
section.PageSetup.DifferentFirstPageHeaderFooter = true;

// Set first page header (can be left empty to hide header on first page)
Paragraph firstHeaderPara = section.HeadersFooters.FirstPageHeader.AddParagraph();
TextRange firstHeaderText = firstHeaderPara.AppendText("First Page Specific Header");
firstHeaderPara.Format.HorizontalAlignment = HorizontalAlignment.Center;

// Set regular header (for pages other than the first page)
Paragraph headerPara = section.HeadersFooters.Header.AddParagraph();
TextRange headerText = headerPara.AppendText("Regular Header");
headerPara.Format.HorizontalAlignment = HorizontalAlignment.Right;

// Save the document
doc.SaveToFile("FirstPageHeader.docx", FileFormat.Docx);
doc.Dispose();

The generated document's header and footer are shown below:

The FirstPageHeader and FirstPageFooter properties can be used to set the header and footer of the first page by setting the DifferentFirstPageHeaderFooter attribute to true.

Changing the Height of the Header and Footer

The HeaderDistance and FooterDistance properties allow you to change the height of headers and footers:

By setting the DifferentFirstPageHeaderFooter property to true, the first page's header and footer can be set using the FirstPageHeader and FirstPageFooter properties.

Adjusting Header and Footer Height
The height of headers and footers can be adjusted through the HeaderDistance and FooterDistance properties:
using Spire.Doc;
using Spire.Doc.Documents;

// Load the document
Document doc = new Document();
doc.LoadFromFile("Sample.docx");

// Get the first section
Section section = doc.Sections[0];

// Set the distance from the header to the top of the page (unit: points)
section.PageSetup.HeaderDistance = 50;

// Set the distance from the footer to the bottom of the page (unit: points)
section.PageSetup.FooterDistance = 50;

// Add header content
HeaderFooter header = section.HeadersFooters.Header;
Paragraph headerPara = header.AddParagraph();
headerPara.AppendText("Header with Adjusted Height");

// Save the document
doc.SaveToFile("AdjustedHeight.docx", FileFormat.Docx);
doc.Dispose();


Below is a preview of the generated Word document:

Practical Tips
Adding Page Number Formats
Page numbers are the most common element in footers and can be added in various formats:
Paragraph footerParagraph = footer.AddParagraph();

// Add "Page X" format
footerParagraph.AppendText("Page ");
footerParagraph.AppendField("page number", FieldType.FieldPage);

// Add "Page X of Y" format
footerParagraph.AppendText("Page ");
footerParagraph.AppendField("page number", FieldType.FieldPage);
footerParagraph.AppendText(" of ");
footerParagraph.AppendField("number of pages", FieldType.FieldNumPages);

Adding Separator Lines
Adding separator lines to headers or footers can enhance visual effects:
// Add separator line at the bottom of the header
headerParagraph.Format.Borders.Bottom.BorderType = BorderStyle.Single;
headerParagraph.Format.Borders.Bottom.Color = Color.Gray;
headerParagraph.Format.Borders.Bottom.LineWidth = 0.5f;

// Add separator line at the top of the footer
footerParagraph.Format.Borders.Top.BorderType = BorderStyle.Single;
footerParagraph.Format.Borders.Top.Color = Color.Gray;
footerParagraph.Format.Borders.Top.LineWidth = 0.5f;


Setting Image Size and Position
When adding images to headers and footers, the image position can be precisely controlled:
DocPicture picture = headerParagraph.AppendPicture(Image.FromFile("Logo.png"));

// Set image size
picture.Width = 40;
picture.Height = 40;

// Set text wrapping style
picture.TextWrappingStyle = TextWrappingStyle.Behind;

// Set horizontal position
picture.HorizontalOrigin = HorizontalOrigin.Page;
picture.HorizontalAlignment = ShapeHorizontalAlignment.Left;

// Set vertical position
picture.VerticalOrigin = VerticalOrigin.Page;
picture.VerticalAlignment = ShapeVerticalAlignment.Top;


Summary

This article has introduced various methods for adding and customizing headers and footers in Word documents using C#, including adding text and images, setting different headers and footers for odd and even pages, special handling for the first page, adjusting height, and other common operations. These techniques enable efficient batch processing of documents and automated header and footer configuration.

In practical applications, these methods can be combined according to specific requirements. For example, professional headers and footers containing company logos, document titles, and page numbers can be created for formal reports, or different header and footer styles for odd and even pages can be set up for book typesetting. Mastering these techniques can significantly improve the efficiency and standardization of document processing.



European ASP.NET Core 10.0 Hosting - HostForLIFE :: How to Use the Outbox Pattern for Microservices in .NET?

clock April 10, 2026 09:05 by author Peter

Ensuring dependable message delivery across services is one of the largest issues developers encounter in contemporary microservices architecture using.NET and ASP.NET Core. There is always a chance of failure when your application needs to send a message (for instance, to a message broker like Kafka or RabbitMQ) in addition to performing a database operation.

 

For example:

  • The database stores the data.
  • However, the message is not published.

Data inconsistency results from this, which is a major issue in distributed systems.

We employ the Outbox Pattern in.NET microservices to address this problem.

This post will explain the Outbox Pattern in layman's terms and show us how to use ASP.NET Core and Entity Framework Core to implement it step-by-step.

What is the Outbox Pattern?
The Outbox Pattern is a design pattern used to ensure that database changes and messages are saved together reliably.

In simple words
Instead of sending messages directly:

  • Save the message in a database table (Outbox table)
  • Later, a background service reads and publishes it

This ensures:

  • No message is lost
  • Data consistency is maintained

Why Do We Need the Outbox Pattern?
In a typical microservices system:

  • You update your database
  • Then you publish an event

But what if:

  • Database save succeeds
  • Message publishing fails?
  • This creates inconsistency.

The Outbox Pattern solves this by:

  1. Storing both data and message in the same transaction
  2. Publishing messages later safely

Real-Life Example
Imagine an e-commerce system:

  • Order is placed
  • Database is updated
  • Event "OrderCreated" should be sent

Without Outbox:
If event fails → other services never know about the order

With Outbox:

  • Event is stored in DB
  • It will be sent eventually

How Outbox Pattern Works
The flow is simple:

  • Application saves business data
  • Application also saves event in Outbox table
  • Both operations happen in a single transaction
  • Background worker reads Outbox table
  • Publishes messages to message broker
  • Marks message as processed

This guarantees eventual consistency in distributed systems.

Step 1: Create Outbox Table

First, create an Outbox entity.
public class OutboxMessage
{
    public Guid Id { get; set; }
    public string Type { get; set; }
    public string Payload { get; set; }
    public DateTime CreatedAt { get; set; }
    public bool Processed { get; set; }
}


Add it to DbContext:
public DbSet<OutboxMessage> OutboxMessages { get; set; }

Step 2: Save Data and Event Together
When saving business data, also save the event.
public async Task CreateOrder(Order order)
{
    _context.Orders.Add(order);

    var message = new OutboxMessage
    {
        Id = Guid.NewGuid(),
        Type = "OrderCreated",
        Payload = JsonSerializer.Serialize(order),
        CreatedAt = DateTime.UtcNow,
        Processed = false
    };

    _context.OutboxMessages.Add(message);

    await _context.SaveChangesAsync();
}

Key point
Both operations happen in one transaction, ensuring reliability.

Step 3: Create Background Service to Process Outbox
Now create a background worker.
public class OutboxProcessor : BackgroundService
{
    private readonly IServiceProvider _serviceProvider;

    public OutboxProcessor(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            using var scope = _serviceProvider.CreateScope();
            var context = scope.ServiceProvider.GetRequiredService<AppDbContext>();

            var messages = await context.OutboxMessages
                .Where(x => !x.Processed)
                .ToListAsync();

            foreach (var message in messages)
            {
                // Publish message (simulate)
                Console.WriteLine($"Publishing: {message.Type}");

                message.Processed = true;
            }

            await context.SaveChangesAsync();

            await Task.Delay(5000);
        }
    }
}

Step 4: Register Background Service
builder.Services.AddHostedService<OutboxProcessor>();

Step 5: Publish Message to Broker (Optional)
Instead of Console.WriteLine, integrate with:

  • RabbitMQ
  • Kafka
  • Azure Service Bus

Example:
await _messageBus.PublishAsync(message.Payload);

Handling Failures and Retries

To make the system robust:

  • Retry failed messages
  • Use exponential backoff
  • Log errors
  • Avoid infinite retries

Add fields like:
public int RetryCount { get; set; }
public string Error { get; set; }

Benefits of Outbox Pattern in .NET

  • Reliable message delivery
  • Prevent data inconsistency
  • Supports eventual consistency
  • Works well with microservices
  • Improves system resilience

Common Challenges

  • Table growth (Outbox table can grow large)
  • Need cleanup strategy
  • Slight delay in message delivery

Best Practices

  • Use batching for processing messages
  • Clean processed messages regularly
  • Use indexing for performance
  • Keep payload small
  • Use JSON serialization carefully

Real-World Use Case

In a payment system:

  • Payment is processed
  • Event is stored in Outbox
  • Notification service receives even

Even if messaging fails initially, it will retry and succeed.

Summary
The Outbox Pattern in .NET microservices is a powerful technique to ensure reliable message delivery and maintain data consistency across distributed systems. By storing events in a database table and processing them asynchronously using a background service, you can avoid message loss and build resilient, scalable applications. This pattern is essential for modern ASP.NET Core microservices that rely on event-driven architecture and message brokers.



European ASP.NET Core 10.0 Hosting - HostForLIFE :: An Introduction to Authentication and Authorization in Contemporary Applications

clock April 1, 2026 08:42 by author Peter

Privacy has never been a choice. Parts of your identification, like your name, email address, and occasionally even your location or payment information, are shared each time you use a service, order food, or log into an app. However, when we click "Login," we typically don't give much thought to what goes on behind the scenes.

Authorization vs. Authentication: The Most Perplexing Ideas
This is still best illustrated by a straightforward real-world example: picture yourself entering a hotel.

They verify your reservation and verify your identity at the front desk. That is authentication, or demonstrating that you are who you say you are.

Now picture yourself attempting to enter a restricted location like the VIP lounge. You might not be permitted entry even if you are a visitor. Authorization is the process of determining what you are permitted to do.

Even now, a lot of systems fail due to poorly designed authorization rather than insufficient authentication.

How We Used to Do It (and Why It Changed)
A few years ago, most applications relied heavily on session-based authentication.
You logged in with a username and password. The server stored your session. Every request depended on that session being valid.

That worked well for simple applications, but it didn't scale well for:

  • Mobile apps
  • Microservices
  • Distributed systems
  • APIs

This is where token-based authentication became the standard.

Tokens: Your Digital Identity Card
Think of a token as a digital ID card.
Instead of asking the server "who are you?" on every request, you just present your token.
The server trusts the token and allows or denies access based on what's inside it.

What is a JWT?

A JWT (JSON Web Token) is a compact, secure way to transmit information between systems.

But here's an important correction from older explanations:

  • A JWT is not inherently secure by itself
  • It is signed (and sometimes encrypted) to ensure integrity

You can think of it as a sealed envelope:

  • Anyone can read it (unless encrypted)
  • But no one can tamper with it without breaking the seal

JWT Structure (Still the Same, Still Important)
A JWT has three parts:
Header
Contains metadata like the signing algorithm (e.g., HS256, RS256)

Payload
Contains claims (data about the user)

Common claims include:

  • sub: user identifier
  • iss: issuer (who created the token)
  • aud: audience (who the token is for)
  • exp: expiration time

Signature
Ensures the token hasn't been modified
One important clarification: The signing algorithm is defined in the Header, not the Signature

OAuth2 and OpenID Connect
OAuth2
OAuth2 is not an authentication protocol.

It is an authorization framework that allows one application to access resources from another on behalf of a user.

Example:
When you click "Login with Google", your app does NOT get your password.

Instead:

  • Google authenticates you
  • Google gives your app a token
  • Your app uses that token to access limited user data

So OAuth2 is about: delegating access, not identifying the user

OpenID Connect (OIDC)

OpenID Connect sits on top of OAuth2 and adds authentication.
It introduces the concept of an ID Token, which is usually a JWT.
This ID token tells your application who the user is

So in modern systems:

  • OAuth2 : authorization (access to resources)
  • OIDC : authentication (identity)
  • Common Mistakes (Still Happening Today)

Even in modern systems, developers still fall into these traps:

1. Putting sensitive data in JWT payload
JWTs are not encrypted by default. Never store passwords or secrets.

2. Not validating tokens properly
Always validate:

  • Signature
  • Expiration
  • Issuer
  • Audience

3. Long-lived tokens
Short-lived access tokens + refresh tokens are the safer approach.

ASP.NET Core Identity
ASP.NET Core Identity is the default membership system provided by Microsoft. It handles everything related to user management.

  • User registration and login
  • Password hashing (secure by default)
  • Roles and claims
  • Token generation

For APIs and modern apps, JWT authentication is the standard.

Instead of sessions, you issue a token after login.

Basic JWT Setup
builder.Services.AddAuthentication("Bearer")
    .AddJwtBearer("Bearer", options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,

            ValidIssuer = "test-app",
            ValidAudience = "test-app",
            IssuerSigningKey = new SymmetricSecurityKey(
                Encoding.UTF8.GetBytes("your-secret-key"))
        };
    });


Authorization (Roles, Claims, Policies)
As mentioned before, authentication tells you who the user is, but authorization defines what they can do.

Role-based authorization

[Authorize(Roles = "Admin")]
public IActionResult AdminOnly()
{
    return Ok("Admin access");
}

Claims-based authorization
[Authorize(Policy = "CanEdit")]
public IActionResult Edit()
{
    return Ok();
}

builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("CanEdit", policy =>
        policy.RequireClaim("permission", "edit"));
});


In modern systems, claims-based or policy-based authorization is preferred over simple roles because it’s more flexible. ASP.NET Core Identity is an interesting topic that i will share about more videos and tutorials for better understanding how it works in the future.



European ASP.NET Core 10.0 Hosting - HostForLIFE :: How Can Developers Control Configuration in Various Application Environments?

clock March 12, 2026 07:48 by author Peter

Seldom do modern software programs operate in a single environment. The majority of systems go through multiple phases, including development, testing, staging, and production. Configurations such as database connections, API endpoints, authentication settings, logging levels, and feature flags may vary depending on the environment. Building scalable and dependable apps requires the management of various setups. Developers may encounter deployment difficulties, security threats, or unexpected system behavior if configuration settings are not managed correctly. Configuration management is essential for preserving consistency across environments in contemporary cloud computing, microservices architectures, and DevOps-driven software development. To handle configuration safely and effectively, developers employ a variety of methods and resources.

Understanding Environment-Specific Configuration
Different environments serve different purposes in the software development lifecycle. Because of this, configuration values often change between environments.
Examples of environment-specific configurations include:

  • Database connection strings
  • API service endpoints
  • Logging and monitoring settings
  • Security credentials
  • Third-party service keys

For example, a development environment may use a local database, while a production environment uses a managed cloud database service. Separating configuration from application code helps developers manage these differences more safely.

Use Environment Variables
One of the most widely used techniques for managing configuration is environment variables. Instead of hardcoding configuration values inside application code, developers store them in environment variables.

Benefits of using environment variables include:

  • Keeps sensitive information out of source code
  • Makes configuration easier to update
  • Supports different settings across environments

Example environment variable configuration:
DATABASE_URL=postgres://localhost:5432/devdb
API_KEY=12345XYZ
NODE_ENV=production

Applications can read these values during runtime.

Example in Node.js:
const dbUrl = process.env.DATABASE_URL;
console.log(dbUrl);


Environment variables are widely supported by cloud platforms, container systems, and deployment pipelines.

Use Configuration Files
Another common approach is storing configuration values in configuration files. These files may use formats such as JSON, YAML, or TOML.

Examples of configuration file formats include:

  • JSON configuration files
  • YAML configuration files
  • Properties files for Java applications

Example JSON configuration file:
{
  "database": "localhost",
  "port": 3000,
  "logLevel": "debug"
}


Configuration files make it easier to organize application settings and maintain readable configuration structures.

Use Configuration Management Tools
In large distributed systems, configuration management tools help centralize configuration settings across multiple services.

Popular configuration management tools include:

  • HashiCorp Consul
  • Spring Cloud Config
  • Kubernetes ConfigMaps
  • AWS Systems Manager Parameter Store

Benefits of configuration management tools include:

  • Centralized configuration storage
  • Dynamic configuration updates
  • Improved security and access control

These tools are widely used in cloud-native architectures and microservices-based systems.

Use Secret Management Systems
Sensitive configuration data such as passwords, encryption keys, and API tokens should never be stored in plain configuration files.
Instead, developers use secret management systems to securely store and access sensitive values.

Examples of secret management tools include:

  • HashiCorp Vault
  • AWS Secrets Manager
  • Azure Key Vault
  • Google Secret Manager

Benefits of secret management systems include:

  • Secure storage of sensitive credentials
  • Controlled access to secrets
  • Automatic rotation of security keys

Using dedicated secret storage significantly improves application security.

Implement Feature Flags

Feature flags allow developers to enable or disable application features without changing code or redeploying the system.
This technique helps teams test new features gradually across different environments.

Examples of feature flag usage include:

  • Enabling a feature only in staging
  • Gradually rolling out a new feature in production
  • Disabling a problematic feature quickly

Feature flag platforms commonly used in modern development include:

  • LaunchDarkly
  • Unleash
  • Split.io

Feature flags provide flexibility and reduce deployment risks.

Use Infrastructure as Code
Modern DevOps practices often use Infrastructure as Code (IaC) tools to manage application environments.
IaC tools allow developers to define infrastructure configuration using code.

Examples of IaC tools include:

  • Terraform
  • AWS CloudFormation
  • Pulumi

Benefits of Infrastructure as Code include:

  • Consistent environment setup
  • Automated infrastructure provisioning
  • Version-controlled infrastructure configuration

Using IaC helps ensure that development, staging, and production environments remain consistent.

Implement Configuration Validation
Configuration errors can cause serious application failures. Developers should validate configuration values during application startup.

Examples of configuration validation checks include:

  • Ensuring required variables exist
  • Verifying database connection settings
  • Checking API key formats

Example validation logic in JavaScript:
if (!process.env.DATABASE_URL) {
  throw new Error("DATABASE_URL is not defined");
}

Configuration validation helps detect problems early during application startup.

Summary
In contemporary software development and DevOps architecture, managing configuration across several environments is an essential technique. Applications frequently operate in development, staging, and production environments, each of which calls for a unique set of configuration parameters. Environment variables, configuration files, centralized configuration management tools, secret management systems, and feature flags are some of the strategies used by developers to handle these variations. These techniques assist guarantee dependable deployments, enhanced security, and consistent behavior across contemporary distributed systems and cloud-native applications when combined with Infrastructure as Code and configuration validation techniques.



European ASP.NET Core 10.0 Hosting - HostForLIFE :: CRUD Project in Multiple Languages Using ASP.NET Core Web API

clock January 6, 2026 06:35 by author Peter

Users from various locations can do the following with a multilingual CRUD application:

  • See information in their native tongue
  • Get messages that are localized
  • Utilize the same API across cultural boundaries

This is frequently utilized in:

  • Platforms for online sales
  • Apps for banks
  • Portals for the government
  • Global SaaS offerings
1. Project Scenario (Real-World Example)
We will build a Product Management API that supports:
  • English (en-US)
  • French (fr-FR)
  • Arabic (ar-SA)
The API will:
  • Create products
  • Read products
  • Update products
  • Delete products
Return localized messages

2. Technologies Used
  • ASP.NET Core Web API
  • Localization (IStringLocalizer)
  • Resource files (.resx)
  • In-memory data (for simplicity)
  • JSON & XML formats
3. Enable Localization in ASP.NET Core
Program.cs Configuration
using Microsoft.AspNetCore.Localization;
using System.Globalization;

builder.Services.AddLocalization(options =>
{
options.ResourcesPath = "Resources";
});

builder.Services.AddControllers()
.AddXmlSerializerFormatters();

var supportedCultures = new[]
{
new CultureInfo("en-US"),
new CultureInfo("fr-FR"),
new CultureInfo("ar-SA")
};

app.UseRequestLocalization(new RequestLocalizationOptions
{
DefaultRequestCulture = new RequestCulture("en-US"),
SupportedCultures = supportedCultures,
SupportedUICultures = supportedCultures
});

app.MapControllers();
app.Run();


4. Product Model
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
}


5. Resource Files Structure
Create a Resources folder:
Resources/
└── Controllers.ProductsController.en-US.resx
└── Controllers.ProductsController.fr-FR.resx
└── Controllers.ProductsController.ar-SA.resx

Resource Keys & Values

English (en-US)

KeyValue
ProductAdded Product added successfully
ProductUpdated Product updated successfully
ProductDeleted Product deleted successfully
ProductNotFound Product not found

French (fr-FR)

KeyValue
ProductAdded Produit ajouté avec succès
ProductUpdated Produit mis à jour avec succès
ProductDeleted Produit supprimé avec succès
ProductNotFound Produit introuvable

6. Products Controller (Localized CRUD)

using Microsoft.Extensions.Localization;

[ApiController]
[Route("api/products")]
public class ProductsController : ControllerBase
{
    private static List<Product> products = new();
    private readonly IStringLocalizer<ProductsController> _localizer;

    public ProductsController(IStringLocalizer<ProductsController> localizer)
    {
        _localizer = localizer;
    }

    [HttpGet]
    public IActionResult GetAll()
    {
        return Ok(products);
    }

    [HttpPost]
    public IActionResult Create(Product product)
    {
        products.Add(product);
        return Ok(new
        {
            Message = _localizer["ProductAdded"],
            Data = product
        });
    }

    [HttpPut("{id}")]
    public IActionResult Update(int id, Product updated)
    {
        var product = products.FirstOrDefault(p => p.Id == id);
        if (product == null)
            return NotFound(_localizer["ProductNotFound"]);

        product.Name = updated.Name;
        product.Price = updated.Price;

        return Ok(_localizer["ProductUpdated"]);
    }

    [HttpDelete("{id}")]
    public IActionResult Delete(int id)
    {
        var product = products.FirstOrDefault(p => p.Id == id);
        if (product == null)
            return NotFound(_localizer["ProductNotFound"]);

        products.Remove(product);
        return Ok(_localizer["ProductDeleted"]);
    }
}

7. Testing with Different Languages
Create Product (English)

Request

POST /api/products
Accept-Language: en-US
Content-Type: application/json

{
  "id": 1,
  "name": "Laptop",
  "price": 1200
}

Response
{
  "message": "Product added successfully",
  "data": {
    "id": 1,
    "name": "Laptop",
    "price": 1200
  }
}


Create Product (French)
Header
Accept-Language: fr-FR

Response
{
  "message": "Produit ajouté avec succès",
  "data": {
    "id": 1,
    "name": "Laptop",
    "price": 1200
  }
}


Delete Product (Arabic)
Request
DELETE /api/products/1
Accept-Language: ar-SA


Response
"تم حذف المنتج بنجاح"

8. XML Request & Response Example
XML Request
POST /api/products
Content-Type: application/xml
Accept-Language: en-US

<Product>
  <Id>2</Id>
  <Name>Mouse</Name>
  <Price>25</Price>
</Product>


XML Response
<object>
  <Message>Product added successfully</Message>
  <Data>
    <Id>2</Id>
    <Name>Mouse</Name>
    <Price>25</Price>
  </Data>
</object>


9. How Culture Is Selected

ASP.NET Core checks (in order):
  • Query string (?culture=fr-FR)
  • Cookies
  • Accept-Language header



European ASP.NET Core 10.0 Hosting - HostForLIFE :: Understanding the .NET Core: An Easy and Comprehensive Guide for Beginners

clock November 20, 2025 08:27 by author Peter

Microsoft's cutting-edge, quick, cross-platform, and open-source framework for creating a wide range of applications, from web apps and APIs to console apps and cloud-native microservices, is called.NET Core (now a part of the.NET 5+ unified platform). For novices who wish to comprehend what.NET Core is, how it functions, and the structure of an actual ASP.NET Core project, this article provides the most straightforward explanation of the framework.

1. What is .NET Core?
.NET Core is Microsoft’s next-generation application development framework, built to overcome the limitations of the old .NET Framework.

Why was .NET Core created?
The old .NET Framework could run only on Windows, was heavy, and was not suitable for cloud, containers, and modern architecture.

.NET Core solves all of these issues.

Key Features of .NET Core
1. Cross-Platform

You can develop and run apps on:

  • Windows
  • Linux
  • macOS

You can host apps on IIS, Apache, Nginx, Kestrel, Docker, or the cloud.

2. Open Source

  • Available on GitHub
  • Anyone can read or contribute to the source code
  • Community-driven improvements

3. High Performance
One of the fastest web frameworks in the world
Handles more traffic with less hardware
Perfect for APIs, enterprise apps, and large-scale cloud systems.

4. Lightweight & Modular

You install only what you need using NuGet packages, which makes applications fast and optimized.

5. Built-in Dependency Injection
Dependency Injection (DI) is built into the framework — no need for third-party libraries.

DI makes apps:

  • Cleaner
  • Easier to test
  • More modular

6. Regular Updates
Microsoft releases new versions every year, including LTS (Long-Term Support) versions for stability.

2. ASP.NET vs ASP.NET Core — What’s the Difference?
ASP.NET Core is a complete redesign of ASP.NET — not just a small upgrade.

FeatureASP.NET (Old)ASP.NET Core (New)
Platform Windows only Windows, Linux, macOS
Performance Average Very fast (up to 4x)
Architecture Monolithic Modular & Lightweight
Hosting IIS only IIS, Kestrel, Nginx, Apache, Self-host
Framework .NET Framework only .NET Core & .NET Framework
Project Types MVC, WebForms, Web API Unified MVC + Web API
Latest Version 4.8.1 .NET 10 (latest)

3. Understanding .NET Core Project Structure

When you create a new ASP.NET Core project, you get several important files and folders. Each plays a special role.
3.1 Program.cs

This is the entry point of your application.

What happens here?
Creates and configures the web host

  • Registers services (Database, Logging, Authentication)
  • Defines the middleware pipeline
  • Maps controllers/endpoints

Think of Program.cs as the “main switchboard” that controls your entire app.

3.2 wwwroot Folder
Everything inside this folder is public.

Used for:

  • CSS files
  • JavaScript
  • Images
  • Bootstrap files

A browser can directly access these files using URLs.
wwwroot = Your public website folder.

3.3 Controllers Folder
Controllers:
Receive HTTP requests
Run logic
Return responses (JSON, HTML, etc.)

Example actions:

  • GET → Read data
  • POST → Create data
  • PUT → Update data
  • DELETE → Remove data

Controllers are like the reception desk of your app.

3.4 appsettings.json
This is your configuration file.

Used for:

  • Database connection strings
  • API keys
  • Logging settings

Email settings
You can also have:
appsettings.Development.json
appsettings.Production.json
appsettings.json is the “control panel” of your project.

3.5 Other Common Folders
Services

Contains business logic.

Data
Contains:

  • DbContext
  • Migrations
  • Entities

Repositories
Handles database CRUD operations.

DTOs
Used to transfer data safely.

These folders are like the “kitchen and back office.”
They do all the behind-the-scenes work.

4. What is Middleware?
Middleware is the heart of ASP.NET Core.
It is a chain of components that process every request and response.

How Middleware Works?
Request → Middleware 1 → Middleware 2 → Middleware 3 → Controller → Response → Back through same middlewares

Key Points About Middleware

  • Runs one-by-one in the order you configure.
  • Can modify request or response.
  • Can stop the request early (called short-circuiting).
  • Used for Logging, Authentication, Routing, Error Handling, etc.

Understanding the Complete Request Pipeline
Let’s break down each stage in the simplest way.

1. Request
When the user sends a request:
Method: GET / POST / PUT / DELETE

URL: /api/products/5

Headers: Auth token, content type

Body: JSON data (for POST/PUT)

2. Logging Middleware
Tracks

  • Which URL was called
  • Who called
  • How long did the request take
  • What was the final status code

Useful for

  • Debugging
  • Performance monitoring
  • Auditing

3. Routing
Matches URL → Correct controller action.

Without routing, the application does not know where to send a request.

4. Authentication
Authentication answers:
“Who are you?”

Examples

  • JWT Token
  • Cookies
  • OAuth

If invalid → Later returns 401 Unauthorized

5. Authorization
Authorization answers:
“Are you allowed to do this?”

Example

  • Admin-only routes
  • Checking user roles
  • Checking user claims

If not allowed → 403 Forbidden

6. Controller Execution
Here, the actual processing happens:

  • Validating data
  • Calling database
  • Applying business rules
  • Returning response (JSON / HTML)

7. Response
Response goes back through the pipeline and finally returns:

  • Status code (200/404/401/403/500)
  • Headers
  • Body (JSON/HTML)

Why Middleware Order Matters?

  • Routing should come before authentication
  • Authentication must come before authorization
  • Static files should be before MVC
  • Error handling needs to be at the top

Incorrect order → Errors like:

  • 404 Not Found
  • 401 Unauthorized
  • Authorization not working

When Things Go Wrong - Quick Fix Guide
401 - Unauthorized

Problem: No identity.
Fix: Check token/cookie + authentication config

403 - Forbidden
Problem: User is known but not allowed.
Fix: Add required roles/claims or change policy

404 - Not Found
Problem: Route not matched.
Fix: Check controller routes and middleware order

Pipeline issues
If things randomly break →
Fix: Ensure correct order:
UseRouting()
UseAuthentication()
UseAuthorization()
MapControllers()



European ASP.NET Core 10.0 Hosting - HostForLIFE :: Understanding WCF Services in .NET with Benefits and an Example

clock October 29, 2025 08:02 by author Peter

Microsoft created the WCF (Windows Communication Foundation) framework to create service-oriented applications. It enables the transmission of data as asynchronous messages between service endpoints. IIS, Windows services, or even self-hosted apps can host these endpoints. Using a variety of protocols, such as HTTP, TCP, Named Pipes, or MSMQ, developers can create secure, dependable, and transactional services with WCF.

Important WCF Features

  • Interoperability: Uses JSON, REST, or SOAP to easily interface with other platforms.
  • Multiple Message Patterns: Facilitates duplex, one-way, and request-reply communication.
  • Security: Integrated authorization, authentication, and encryption.
  • Transaction Support: Guarantees dependable rollback and message delivery.
  • Flexible Hosting: Use a console application, Windows Service, or IIS to host.
  • Extensibility: It is simple to implement custom behaviors, bindings, and contracts.

Overview of the WCF Architecture
A WCF service is built around four key concepts:

LayerDescription
Service Contract Defines the interface for the service (methods exposed).
Data Contract Defines the data structure used for communication.
Binding Defines how the service communicates (protocol, encoding).
Endpoint Specifies the address and communication details of the service.

Example: Simple WCF Service

Let’s create a simple “Calculator Service” using WCF.

Step 1. Define the Service Contract

using System.ServiceModel;

[ServiceContract]
public interface ICalculatorService
{
    [OperationContract]
    int Add(int a, int b);

    [OperationContract]
    int Subtract(int a, int b);
}


Step 2. Implement the Service
public class CalculatorService : ICalculatorService
{
    public int Add(int a, int b) => a + b;
    public int Subtract(int a, int b) => a - b;
}


Step 3. Configure Service in App.config
<system.serviceModel>
  <services>
    <service name="WCFDemo.CalculatorService">
      <endpoint address="" binding="basicHttpBinding" contract="WCFDemo.ICalculatorService" />
      <host>
        <baseAddresses>
          <add baseAddress="http://localhost:8080/CalculatorService"/>
        </baseAddresses>
      </host>
    </service>
  </services>
  <behaviors>
    <serviceBehaviors>
      <behavior>
        <serviceMetadata httpGetEnabled="true"/>
        <serviceDebug includeExceptionDetailInFaults="true"/>
      </behavior>
    </serviceBehaviors>
  </behaviors>
</system.serviceModel>


Step 4. Host the Service (Console Example)
using System;
using System.ServiceModel;

class Program
{
    static void Main()
    {
        using (ServiceHost host = new ServiceHost(typeof(CalculatorService)))
        {
            host.Open();
            Console.WriteLine("WCF Calculator Service is running...");
            Console.WriteLine("Press any key to stop.");
            Console.ReadKey();
        }
    }
}


Step 5. Consume the Service (Client Side)
Add a Service Reference in your client project → Enter the service URL (e.g., http://localhost:8080/CalculatorService?wsdl).

Then, you can use:
var client = new CalculatorServiceClient();
Console.WriteLine(client.Add(10, 20));  // Output: 30

Benefits of Using WCF

BenefitDescription
Interoperability Communicates with any platform that supports SOAP or REST.
Scalability Easily scale your services with multiple bindings and endpoints.
Security Integrated support for authentication, encryption, and authorization.
Reliable Messaging Ensures delivery even under network failure.
Extensible and Flexible Add custom behaviors and message inspectors.
Multiple Hosting Options Host in IIS, Windows Service, or Self-Hosted app.

Common WCF Bindings

BindingProtocolUse Case
basicHttpBinding HTTP Interoperable web services (SOAP 1.1).
wsHttpBinding HTTP Secure and reliable SOAP services.
netTcpBinding TCP High performance within intranet.
netNamedPipeBinding Named Pipes On-machine communication.
netMsmqBinding MSMQ Message queuing for disconnected apps.
webHttpBinding HTTP RESTful services (with JSON/XML).

Conclusion

WCF remains a powerful framework for building service-oriented, secure, and scalable communication systems.
While modern APIs often use ASP.NET Core Web APIs or gRPC, WCF continues to be a great choice for enterprise-grade distributed applications that require SOAP, WS-Security, and transactional messaging.



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.


Month List

Tag cloud

Sign in