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 :: ASP.NET Core Exception Handling

clock December 8, 2025 08:11 by author Peter

One of the most crucial components of creating reliable, safe, and production-ready apps is exception management. Errors such as faulty input, network failures, database connection problems, unhandled null values, or unauthorized access are eventually encountered by every application. The difficulty lies not in preventing these mistakes but in managing them consistently and with grace.


An extensive and potent exception-handling pipeline is offered by ASP.NET Core. Using real-world examples, global middleware, logging, structured API answers, custom exceptions, and recommended practices, this article covers exception handling from the fundamentals to sophisticated methods.

1. What is an Exception?
An exception is an unexpected event that occurs during program execution and disrupts the normal flow of the application.
Common examples include:

  • Trying to divide by zero
  • Attempting to read null values
  • Accessing invalid array indexes
  • Database connection failures
  • Invalid type conversions

Exceptions help developers identify problems, but unhandled exceptions cause application crashes. This is why exception handling is essential.

2. Why Exception Handling Is Important
Proper exception handling provides several benefits:

  • Prevents application crashes
  • Displays user-friendly messages
  • Prevents sensitive information from leaking
  • Produces reliable API responses
  • Helps developers diagnose issues through logs
  • Improves maintainability and robustness

Without exception handling, end users may see application crashes or confusing error pages. With proper handling, errors become predictable, controlled, and secure.

3. Types of Exceptions in .NET

System Exceptions
These are built-in .NET exception types, such as:

  • NullReferenceException
  • ArgumentException
  • InvalidOperationException
  • FormatException
  • IndexOutOfRangeException

Application Exceptions
Custom exceptions created by developers to handle logical or business-related issues:
public class InvalidOrderException : Exception
{
    public InvalidOrderException(string message) : base(message) { }
}

Business Rule Exceptions
These represent domain-level issues, such as:

  • Insufficient balance
  • Invalid order ID
  • Inactive account
  • Unauthorized operation

4. Try–Catch–Finally - Basic Exception Handling
The simplest form of exception handling uses try, catch, and finally blocks.
try
{
    int x = 10;
    int y = 0;
    int result = x / y;
}
catch (DivideByZeroException ex)
{
    Console.WriteLine("Cannot divide by zero.");
}
catch (Exception ex)
{
    Console.WriteLine("An unexpected error occurred.");
}
finally
{
    Console.WriteLine("This block always executes.");
}


The finally block is optional and is typically used to release resources like database connections or file handles.

5. Exception Handling in ASP.NET Core
ASP.NET Core offers several layers of exception handling:

  • Developer exception page
  • Production exception handler using UseExceptionHandler
  • Custom global exception handling middleware
  • Exception filters
  • Validation responses
  • Structured error responses (Problem Details)
  • Logging via ILogger or external log providers

Each technique has a specific use case depending on whether you are in development or production.

6. Developer Exception Page - Development Environment
This provides detailed error information, including:

  • Stack trace
  • Source file and line number
  • Error message
  • Request details

Enable it only in development:
if (app.Environment.IsDevelopment())
{
    app.UseDeveloperExceptionPage();
}

Never enable this in production because it exposes sensitive details.

7. Built-in Production Exception Handler - UseExceptionHandler
This middleware catches unhandled exceptions globally.

Step 1: Enable the handler in Program.cs

app.UseExceptionHandler("/error");

Step 2: Create the error endpoint
app.Map("/error", (HttpContext context) =>
{
    return Results.Problem("An unexpected error occurred.");
});


This handles all unhandled exceptions without exposing internal details.

8. Global Exception Handling Middleware - Preferred Method

Creating a custom middleware provides full control and centralizes all exception handling logic.

ExceptionMiddleware.cs
using System.Net;
using System.Text.Json;

public class ExceptionMiddleware : IMiddleware
{
    public async Task InvokeAsync(HttpContext context, RequestDelegate next)
    {
        try
        {
            await next(context);
        }
        catch (Exception ex)
        {
            context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
            context.Response.ContentType = "application/json";

            var errorResponse = new
            {
                StatusCode = context.Response.StatusCode,
                Message = "An unexpected error occurred.",
                Detail = ex.Message
            };

            var json = JsonSerializer.Serialize(errorResponse);
            await context.Response.WriteAsync(json);
        }
    }
}

Register in the Program.cs
builder.Services.AddTransient<ExceptionMiddleware>();
app.UseMiddleware<ExceptionMiddleware>();


This approach is suitable for production APIs.

9. Exception Filters - MVC Specific
Exception filters allow centralized handling for controller actions.

CustomExceptionFilter.cs
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;

public class CustomExceptionFilter : IExceptionFilter
{
    public void OnException(ExceptionContext context)
    {
        context.Result = new JsonResult(new
        {
            Message = "An error occurred.",
            Detail = context.Exception.Message
        })
        { StatusCode = 500 };
    }
}

Register in the Program.cs
builder.Services.AddControllers(options =>
{
    options.Filters.Add<CustomExceptionFilter>();
});


Filters are useful when you want exception handling only for controllers, not for middleware-level requests.

10. Validation Exception Handling
ASP.NET Core automatically validates DTOs using data annotations.

Example DTO:
public class RegisterDto
{
    [Required]
    public string Email { get; set; }

    [MinLength(6)]
    public string Password { get; set; }
}

When validation fails, ASP.NET Core returns a structured 400 response:
{
  "errors": {
    "Password": ["The field Password must be a string with a minimum length of 6."]
  }
}

No additional exception handling is required for validation errors.

11. Structured Error Responses Using ProblemDetails
ASP.NET Core supports the Problem Details format (RFC 7807).

Example:
return Problem(
    title: "Internal Server Error",
    detail: "Database connection failed",
    statusCode: 500
);

This produces a structured response:
{
  "title": "Internal Server Error",
  "status": 500,
  "detail": "Database connection failed"
}


Consistent error responses improve debugging and client-side error handling.

12. Logging Exceptions Using ILogger
Logging is critical for diagnosing issues and monitoring applications.
try
{
    int.Parse("abc");
}
catch (Exception ex)
{
    _logger.LogError(ex, "Error while parsing number");
}


Logging providers supported in ASP.NET Core:

  • Console logging
  • Debug logging
  • Serilog
  • NLog
  • Seq
  • Application Insights

Logs should be centralized in production.

13. Custom Business Exceptions
Applications often need domain-level error handling.
public class InsufficientFundsException : Exception
{
    public InsufficientFundsException(string message) : base(message) { }
}

Usage:
if (balance < amount)
    throw new InsufficientFundsException("Insufficient funds to complete transaction.");


Catch these globally and return user-friendly messages.

14. Real-World Example: Handling Exceptions in a Controller
[HttpGet("{id}")]
public async Task<IActionResult> GetOrder(int id)
{
    var order = await _context.Orders.FindAsync(id);

    if (order == null)
        throw new KeyNotFoundException("Order not found");

    return Ok(order);
}


Global middleware converts this into a structured error response without exposing sensitive details.

15. Best Practices for Exception Handling in Production

  • Never expose internal exception messages to users
  • Always log exceptions with proper context
  • Use global exception handling middleware
  • Standardize error responses with ProblemDetails
  • Use try-catch only where required
  • Validate user input before processing
  • Create custom exceptions for business logic
  • Return proper HTTP status codes
  • Separate domain, application, and infrastructure exceptions

Proper exception handling improves code quality, application reliability, and security. Thank you for reading this complete guide on Exception Handling in ASP.NET Core. Exception handling is a critical skill for building stable, secure, and maintainable applications. By implementing global handlers, logging, structured responses, and custom exception logic, you ensure your APIs remain predictable and professional under all circumstances.



European ASP.NET Core 10.0 Hosting - HostForLIFE :: Learning SqlHelper Class in .NET: ExecuteNonQuery, ExecuteDataset, ExecuteScalar

clock December 5, 2025 06:15 by author Peter

The same database tasks are frequently repeated while using Microsoft SQL Server in a.NET application:

  • Creating SQL connections
  • Making commands
  • Running queries
  • Completing DataSets
  • Giving back values

Developers make a reusable SQL Helper class to avoid repeatedly writing this boilerplate code.
Commonly used database execution techniques are provided by your SqlHelper class, including:

  • Execute Dataset
  • Run NonQuery
  • Run Scalar

Each technique is described in this article along with its rationale and useful, real-world examples.

ExecuteDataset — Fetching Records (SELECT Queries)

Purpose
To execute SELECT queries and return the result as a DataSet.

Why used?
When you need multiple tables or multiple rows

When UI needs table-like data (GridView, DataTable, Excel Export etc.)

A. ExecuteDataset (Text Query)

public DataSet ExecuteDataset(string conStr, string query)
{
    DataSet ds = new DataSet();

    using (SqlConnection con = new SqlConnection(conStr))
    {
        con.Open();
        using (SqlDataAdapter da = new SqlDataAdapter(query, con))
        {
            da.Fill(ds);
        }
    }

    return ds;
}


Real-Time Use Case
Example: Fetch IPO Master list from database and show in grid.

Example Code
SqlHelper helper = new SqlHelper();
DataSet ds = SqlHelper.ExecuteDataset(conStr, "SELECT * FROM  Userdetails");


if (ds.Tables[0].Rows.Count > 0)
{
    // Bind to Grid or dropdown
}


B. ExecuteDataset (Stored Procedure)
public static DataSet ExecuteDataset(string conStr, string proc, SqlParameter[] param, bool isSp)
{
    DataSet ds = new DataSet();

    using (SqlConnection con = new SqlConnection(conStr))
    {
        con.Open();
        using (SqlCommand cmd = new SqlCommand(proc, con))
        {
            cmd.CommandType = isSp ? CommandType.StoredProcedure : CommandType.Text;
            cmd.Parameters.AddRange(param);

            using (SqlDataAdapter da = new SqlDataAdapter(cmd))
            {
                da.Fill(ds);
            }
        }
    }

    return ds;
}

Real-Time Use Case

When your project requires fetching data using a stored procedure with parameters.

Example: Get User details based on ID.

Example Code
SqlParameter[] param =
{
    new SqlParameter("@Id", 25)
};


DataSet ds = SqlHelper.ExecuteDataset(
    conStr,
    "sp_GetDetails",
    param,
    true
);

ExecuteNonQuery — Insert, Update, Delete (No Data Returned)
Purpose
For queries that do not return rows:

  • INSERT
  • UPDATE
  • DELETE

Stored procedures performing actions

Why used?
To know how many rows were affected.

A. ExecuteNonQuery (Stored Procedure with Parameters)
public int ExecuteNonQuery(string conStr, string proc, SqlParameter[] param, bool isSp)
{
    using (SqlConnection con = new SqlConnection(conStr))
    {
        con.Open();
        using (SqlCommand cmd = new SqlCommand(proc, con))
        {
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.Parameters.AddRange(param);

            return cmd.ExecuteNonQuery();
        }
    }
}

Real-Time Use Case
Example: Save IPO Application values (Insert).

Example Code
SqlParameter[] param =
{
    new SqlParameter("@AppNo", "12345"),
    new SqlParameter("@InvestorName", "Sandhiya")
};


SqlHelper helper = new SqlHelper();
int rows = helper.ExecuteNonQuery(
    conStr,
    "sp_InsertApplication",
    param,
    true
);

if (rows > 0)
{
    Console.WriteLine("Record Inserted Successfully!");
}


B. ExecuteNonQuery (Static)
public static int ExecuteNonQuery(string connectionString, CommandType cmdType, string cmdText)
{
    using SqlConnection conn = new SqlConnection(connectionString);
    using SqlCommand cmd = new SqlCommand(cmdText, conn);
    cmd.CommandType = cmdType;
    conn.Open();
    return cmd.ExecuteNonQuery();
}


Real-Time Use Case
When you want a simple command without parameters.

Example
int rows = SqlHelper.ExecuteNonQuery(
    conStr,
    CommandType.Text,
    "DELETE FROM TempTable"
);


ExecuteScalar Return Single Value
Purpose
To get one single value from the database.

Used When?

  • COUNT()
  • SUM()
  • MAX()
  • MIN()
  • Get latest inserted ID

Example: Count total User records
public static object ExecuteScalar(string connectionString, CommandType cmdType, string cmdText)
 {
     using SqlConnection conn = new SqlConnection(connectionString);
     using SqlCommand cmd = new SqlCommand(cmdText, conn);
     cmd.CommandType = cmdType;
     conn.Open();
     return cmd.ExecuteScalar();
 }
object count = SqlHelper.ExecuteScalar(
    conStr,
    CommandType.Text,
    "SELECT COUNT(*) FROM IPOMaster"
);


Console.WriteLine("Total IPO: " + count);

ExecuteDataset (Another Static Version)
public static DataSet ExecuteDataset(string connectionString, CommandType cmdType, string cmdText)
{
    using SqlConnection conn = new SqlConnection(connectionString);
    using SqlCommand cmd = new SqlCommand(cmdText, conn);
    cmd.CommandType = cmdType;

    using SqlDataAdapter da = new SqlDataAdapter(cmd);
    DataSet ds = new DataSet();
    da.Fill(ds);
    return ds;
}


Purpose

Same as other ExecuteDataset but used when the developer doesn’t need parameters.

Example
DataSet ds = SqlHelper.ExecuteDataset(
    conStr,
    CommandType.Text,
    "SELECT * FROM Users"
);


Difference Between All Methods (Quick Table)

MethodPurposeReturnsUse Case
ExecuteDataset SELECT queries DataSet Fetch rows, tables
ExecuteNonQuery INSERT, UPDATE, DELETE int (affected rows) Save, update, delete data
ExecuteScalar Single value queries object COUNT(), MAX(), ID
ExecuteDataset (SP) Stored procedure results DataSet Query with parameters
ExecuteNonQuery (SP) Stored procedure actions Affected rows Insert/update using SP


European ASP.NET Core 10.0 Hosting - HostForLIFE :: ASP.NET Core's Safe Password Storage

clock November 25, 2025 06:49 by author Peter

The first line of defense in each application is a password. Inadequate storage can result in catastrophic breaches. If used properly, ASP.NET Core Identity provides a safe, industry standard solution.

How Passwords Are Stored in ASP.NET Core?
Passwords are stored by ASP.NET Core Identity using:

  • The hashing algorithm PBKDF2
  • Per-user salt at random
  • Over 10,000 iterations
  • IdentityV3 password hash is a secure format.

This guarantees that no two passwords result in the same hash.

Never Store Plain Text Passwords
Example of what not to do:
user.Password = model.Password; //Insecure way of storing password

If your database gets leaked, all passwords are exposed.

Use Identity Password Hasher
ASP.NET Core Identity automatically hashes passwords:
await _userManager.CreateAsync(user, model.Password);

If you're building a custom user system:
var hashedPassword = _passwordHasher.HashPassword(user, password);

Verification
_passwordHasher.VerifyHashedPassword(user, hashedPassword, providedPassword);

Password Salting

Salt is a random string added before hashing to prevent:

  • Rainbow table attacks
  • Hash collisions

ASP.NET Core Identity generates salt automatically. No need to manage it yourself.

Password Peppering
Pepper is a secret stored outside the DB (in environment variables / Key Vault). It’s an optional extra security.

Example
string pepper = config["PasswordPepper"];
string passwordWithPepper = password + pepper;
var hash = _passwordHasher.HashPassword(user, passwordWithPepper);


Use only in custom implementations—not required for Identity. 

Password Strength Requirements
Configure password policy:
builder.Services.Configure<IdentityOptions>(options =>
{
    options.Password.RequireDigit = true;
    options.Password.RequireLowercase = true;
    options.Password.RequireUppercase = true;
    options.Password.RequiredLength = 8;
});


Force Users to Change Password Regularly
Store last password change date and enforce:
if(user.LastPasswordChangeDate < DateTime.UtcNow.AddMonths(-3))
{
    return Redirect("/Account/ForceChangePassword");
}


Prevent Password Reuse
Store password history hashes:
var oldHashes = await _db.PasswordHistory
    .Where(x => x.UserId == user.Id)
    .Select(x => x.HashedPassword)
    .ToListAsync();


Reject if match
if(_passwordHasher.VerifyHashedPassword(user, oldHash, newPassword)
   != PasswordVerificationResult.Failed)
{
    return "Password already used.";
}


Enable Email Confirmation

Enable email confirmation so only users with a valid email address can activate their account. This also prevents attackers from registering fake accounts.

Use HTTPS Everywhere

Always force to use HTTPS so that passwords and login data stay encrypted and safe while being sent between the user and the server.
app.UseHttpsRedirection();

Conclusion

Storing passwords securely requires:

  • Strong hashing (PBKDF2)
  • Salt (built-in)
  • Optional pepper
  • Strong password policy
  • HTTPS
  • Avoiding reuse
  • Periodic changes

ASP.NET Core Identity already does most of the heavy lifting use it!



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 :: Effective Range Requests and File Streaming in ASP.NET Core APIs

clock November 14, 2025 07:03 by author Peter

Large files, like films, PDFs, or CAD models, must frequently be efficiently delivered to consumers by modern web apps. ASP.NET Core enables developers to handle HTTP range requests and stream files instead of loading whole files into memory, allowing clients to restart stopped downloads or download files in part. This approach saves memory, improves performance, and enhances the user experience.

1. Comprehending ASP.NET Core File Streaming
The full file is loaded into memory when using conventional file download techniques like File.ReadAllBytes(), which is ineffective for big files.
In contrast, streaming allows clients to begin receiving material while the remainder of the file is still being read because it transmits data in chunks.
For instance, simple file streaming.

[HttpGet("download/{fileName}")]
public async Task<IActionResult> DownloadFile(string fileName)
{
    var filePath = Path.Combine("Files", fileName);

    if (!System.IO.File.Exists(filePath))
        return NotFound("File not found.");

    var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
    return File(stream, "application/octet-stream", fileName);
}

Key Points
The file is not fully loaded into memory.
ASP.NET Core handles streaming automatically using FileStreamResult.

Ideal for large media files or document downloads.

2. Supporting Range Requests for Partial Downloads
Modern browsers and video players often request byte ranges instead of entire files to support:

Resumable downloads
Media streaming (e.g., MP4 playback)

Efficient caching
You can manually implement HTTP range handling to support these cases.

Example: Range Request Implementation
[HttpGet("stream/{fileName}")]
public async Task<IActionResult> StreamFile(string fileName)
{
    var filePath = Path.Combine("Files", fileName);

    if (!System.IO.File.Exists(filePath))
        return NotFound();

    var fileInfo = new FileInfo(filePath);
    var fileLength = fileInfo.Length;
    var rangeHeader = Request.Headers["Range"].ToString();

    if (string.IsNullOrEmpty(rangeHeader))
        return PhysicalFile(filePath, "application/octet-stream", enableRangeProcessing: true);

    // Parse range
    var range = rangeHeader.Replace("bytes=", "").Split('-');
    var start = long.Parse(range[0]);
    var end = range.Length > 1 && !string.IsNullOrEmpty(range[1]) ? long.Parse(range[1]) : fileLength - 1;
    var contentLength = end - start + 1;

    Response.StatusCode = StatusCodes.Status206PartialContent;
    Response.Headers.Add("Accept-Ranges", "bytes");
    Response.Headers.Add("Content-Range", $"bytes {start}-{end}/{fileLength}");
    Response.Headers.Add("Content-Length", contentLength.ToString());

    using var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
    fs.Seek(start, SeekOrigin.Begin);
    var buffer = new byte[64 * 1024]; // 64KB buffer

    long remaining = contentLength;
    while (remaining > 0)
    {
        var count = (int)Math.Min(buffer.Length, remaining);
        var read = await fs.ReadAsync(buffer, 0, count);
        if (read == 0) break;
        await Response.Body.WriteAsync(buffer.AsMemory(0, read));
        remaining -= read;
    }

    return new EmptyResult();
}

What Happens Here?
The API reads the Range header from the client request.

It calculates the byte segment to send.

The file is streamed incrementally, allowing pause/resume functionality.

3. Enabling Range Processing Automatically
ASP.NET Core provides built-in range processing for static or physical files:
app.UseStaticFiles(new StaticFileOptions
{
    ServeUnknownFileTypes = true,
    OnPrepareResponse = ctx =>
    {
        ctx.Context.Response.Headers.Append("Accept-Ranges", "bytes");
    }
});


Alternatively, you can use PhysicalFile() or VirtualFile() with:
return PhysicalFile(filePath, "application/pdf", enableRangeProcessing: true);

This is ideal when you want a simple and efficient approach without manually parsing headers.

4. Real-World Use Cases
Video Streaming Platforms – Serve MP4 files efficiently using range-based streaming.
Document Viewers (PDF, DOCX) – Load only required file sections for faster rendering.
AutoCAD or 3D File Renderers – Fetch model data progressively for WebGL visualization.
Download Managers – Enable users to pause/resume downloads seamlessly.

5. Performance Optimization Tips
Use asynchronous file I/O (await fs.ReadAsync) to avoid blocking threads.

  • Keep buffer sizes between 32KB–128KB for optimal throughput.
  • Serve large files from Azure Blob Storage, AWS S3, or CDN when possible.
  • Cache metadata (file size, last modified) to reduce disk I/O.

Conclusion
Scalability, enhanced user experience, and effective resource use are guaranteed when file streaming and range requests are implemented in ASP.NET Core.
These methods let you manage contemporary client expectations, such resumable downloads and media streaming, without overtaxing your server memory, whether you're offering PDFs, movies, or big datasets.

You may create a versatile, high-performance file distribution system that satisfies user and company requirements by fusing custom streaming logic with ASP.NET Core's built-in range processing.



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.



European ASP.NET Core 10.0 Hosting - HostForLIFE :: DebuggerDisplay Makes Debugging in.NET Easier

clock October 27, 2025 07:34 by author Peter

Tired of seeing {MyApp.Models.Customer} when checking objects in Visual Studio? [DebuggerDisplay] can help. Added in .NET Framework 2.0 and still supported in modern .NET (Core, 5–9), it lets you control how objects show up in the debugger, making it easier to understand your data.

The tools that I have used below:

  • VS 2026 Insider

  • .NET 9.0

  • Console App

Example
using System.Diagnostics;

namespace DebuggerDisplayExample
{

    [DebuggerDisplay("Name = {Name}, Age = {Age}, FavoriteLanguage = {FavoriteLanguage}")]
    internal class Developer
    {
        public string Name { get; set; }
        public int Age { get; set; }
        public string FavoriteLanguage { get; set; }
        public Developer(string name, int age, string favoriteLanguage)
        {
            Name = name;
            Age = age;
            FavoriteLanguage = favoriteLanguage;
        }

        [DebuggerDisplay("{DebuggerDisplay,nq}")]
        private string DebuggerDisplay => $"Name = {Name}, Age = {Age}, FavoriteLanguage = {FavoriteLanguage}";
    }
}

Hovering over a developer now shows as below:

Much clearer than the default type name. For more complex objects, use a private helper property with nq to remove quotes:

Why Use It?

  • Makes debugging collections and domain models faster.
  • Shows a clear, readable summary without changing your code at runtime.
  • Supported in all .NET versions from 2.0 to 9.0.

Even after 20 years, [DebuggerDisplay] is a tiny feature that makes a big difference—it shows that small improvements today, like making objects easier to read in the debugger, can save you a lot of time and frustration later. Happy Coding!



ASP.NET Core 8 Hosting - HostForLIFE.eu :: Constructing a .NET 8 Generative AI Microservice

clock October 20, 2025 07:44 by author Peter

With generative AI's explosive growth, developers are no longer constrained to static business logic. The ability to build, summarize, explain, and even dynamically generate code or SQL queries has been added to applications. Generative AI APIs (such as Hugging Face, Azure OpenAI, or OpenAI) with.NET 8 can be combined to create intelligent microservices that can generate and comprehend natural language. Learn how to create a microservice driven by generative AI in this tutorial by utilizing the OpenAI GPT API and.NET 8 Minimal APIs.

Step 1. Create a New .NET 8 Web API Project
In your terminal or command prompt:
dotnet new webapi -n GenerativeAIMicroservice
cd GenerativeAIMicroservice

Step 2. Clean Up the Template
Remove default controllers and WeatherForecast examples.
We’ll use a Minimal API style for simplicity.

Step 3. Add Dependencies
Install the following NuGet packages:
dotnet add package OpenAI_API
dotnet add package Newtonsoft.Json

These allow communication with the OpenAI GPT API and handle JSON serialization.

Step 4. Create the AI Service
Create a new file: Services/AiService.cs
using OpenAI_API;
using System.Threading.Tasks;

namespace GenerativeAIMicroservice.Services
{
    public class AiService
    {
        private readonly OpenAIAPI _api;

        public AiService(string apiKey)
        {
            _api = new OpenAIAPI(apiKey);
        }

        public async Task<string> GenerateTextAsync(string prompt)
        {
            var result = await _api.Completions.GetCompletion(prompt);
            return result;
        }
    }
}


This service will handle all Generative API communication.

Step 5. Create the Minimal API Endpoint
In your Program.cs file, add:
using GenerativeAIMicroservice.Services;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton(new AiService("sk-your-openai-api-key"));  // Replace with your key

var app = builder.Build();

app.MapPost("/api/generate", async (AiService aiService, PromptRequest request) =>
{
    if (string.IsNullOrEmpty(request.Prompt))
        return Results.BadRequest("Prompt is required.");

    var response = await aiService.GenerateTextAsync(request.Prompt);
    return Results.Ok(new { Output = response });
});

app.Run();

record PromptRequest(string Prompt);


Example Request
You can now test your Generative API microservice using Postman or curl.
POST Request

URL:
https://localhost:5001/api/generate

Body (JSON):
{"Prompt": "Write a C# function to reverse a string"}

Example Response
{"Output": "public string ReverseString(string s) { char[] arr = s.ToCharArray(); Array.Reverse(arr); return new string(arr); }"}

Step 6. Containerize with Docker (Optional)
To make it cloud-ready, create a Dockerfile:
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
WORKDIR /app

FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
COPY . .
RUN dotnet publish -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=build /app/publish .
ENTRYPOINT ["dotnet", "GenerativeAIMicroservice.dll"]

Then run:
docker build -t generative-ai-service .
docker run -p 8080:80 generative-ai-service

Step 7. Real-World Use Cases

ScenarioDescription

Code Assistant

Generate code snippets based on developer prompts

Chatbot Backend

Provide intelligent responses in chat systems

SQL Generator

Convert text prompts into database queries

Content Creation

Auto-generate text, descriptions, and blogs

AI Documentation Service

Summarize and document APIs automatically

Architecture Overview

Client App (UI)

Generative AI Microservice (.NET 8)

OpenAI / Azure OpenAI API

AI-Generated Response

This architecture makes the AI layer modular, secure, and reusable across multiple projects.

Security Considerations
Do not hardcode API keys — use:

dotnet user-secrets set "OpenAIKey" "sk-your-key"

and retrieve it via:

builder.Configuration["OpenAIKey"]

  1. Limit tokens and rate of calls
  2. Sanitize user inputs before sending to AI API
  3. External References

Conclusion
By integrating Generative AI APIs into a .NET 8 microservice, you can bring AI-driven intelligence into any system — whether for content creation, coding automation, or chatbot applications. This architecture is modular, scalable, and ready for enterprise deployment, bridging traditional software engineering with next-generation AI development.



European ASP.NET Core 10.0 Hosting - HostForLIFE :: ASP.NET Core's High Performance and Scalability

clock October 13, 2025 08:27 by author Peter

A cutting-edge, cross-platform, open-source framework for creating scalable and high-performance online applications is called ASP.NET Core. Its architecture guarantees that developers can achieve high throughput, low latency, and effective resource usage for everything from microservices to enterprise-grade APIs. In order to optimize performance and scalability in your ASP.NET Core applications, we'll go over important tactics, setting advice, and code samples in this post.

Understanding Performance and Scalability
Before diving into implementation, let’s define two crucial concepts:

  • Performance: How fast your application responds to a single request.

(Example: Reducing response time from 300ms to 100ms).

  • Scalability: How well your application handles increased load.

(Example: Handling 10,000 concurrent users without crashing).

ASP.NET Core achieves both through efficient memory management, asynchronous programming, dependency injection, caching, and built-in support for distributed systems.

Using Asynchronous Programming
The ASP.NET Core runtime is optimized for asynchronous I/O operations. By using the async and await keywords, you can free up threads to handle more requests concurrently.

Example: Asynchronous Controller Action
[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
    private readonly IProductService _productService;

    public ProductsController(IProductService productService)
    {
        _productService = productService;
    }

    [HttpGet("{id}")]
    public async Task<IActionResult> GetProductById(int id)
    {
        var product = await _productService.GetProductAsync(id);

        if (product == null)
            return NotFound();

        return Ok(product);
    }
}

By using Task<IActionResult> , the thread doesn’t block while waiting for I/O-bound operations such as database queries or API calls. This dramatically improves scalability under heavy load.

Optimize Middleware Pipeline
Middleware components handle each request sequentially. Keep your middleware lightweight and avoid unnecessary processing.

Example: Custom Lightweight Middleware
public class RequestTimingMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger<RequestTimingMiddleware> _logger;

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

    public async Task InvokeAsync(HttpContext context)
    {
        var start = DateTime.UtcNow;
        await _next(context);
        var elapsed = DateTime.UtcNow - start;

        _logger.LogInformation($"Request took {elapsed.TotalMilliseconds} ms");
    }
}

// Registration in Program.cs
app.UseMiddleware<RequestTimingMiddleware>();


Tip :
Place lightweight middleware at the top (like routing or compression), and heavy middleware (like authentication) lower in the pipeline.

Enable Response Caching
Caching reduces the need to recompute results or hit the database repeatedly. ASP.NET Core provides a built-in Response Caching Middleware .

Example: Enable Response Caching

// In Program.cs
builder.Services.AddResponseCaching();

var app = builder.Build();
app.UseResponseCaching();

app.MapGet("/time", (HttpContext context) =>
{
    context.Response.GetTypedHeaders().CacheControl =
        new Microsoft.Net.Http.Headers.CacheControlHeaderValue()
        {
            Public = true,
            MaxAge = TimeSpan.FromSeconds(30)
        };

    return DateTime.UtcNow.ToString("T");
});

Now, subsequent requests within 30 seconds will be served from cache — drastically improving performance.

Optimize Data Access with EF Core
Database access is often the main bottleneck. Use Entity Framework Core efficiently by applying:

  • AsNoTracking() for read-only queries
  • Compiled queries for repeated access
  • Connection pooling

Example: Using AsNoTracking()
public async Task<IEnumerable<Product>> GetAllProductsAsync()
{
    return await _context.Products
        .AsNoTracking()  // Improves performance
        .ToListAsync();
}

If you frequently run similar queries, consider compiled queries :
private static readonly Func<AppDbContext, int, Task<Product?>> _getProductById =
    EF.CompileAsyncQuery((AppDbContext context, int id) =>
        context.Products.FirstOrDefault(p => p.Id == id));

public Task<Product?> GetProductAsync(int id) =>
    _getProductById(_context, id);


Use Output Compression
Compressing responses before sending them to the client reduces bandwidth usage and speeds up delivery.

Example: Enable Response Compression
// In Program.cs
builder.Services.AddResponseCompression(options =>
{
    options.EnableForHttps = true;
    options.MimeTypes = new[] { "text/plain", "application/json" };
});

var app = builder.Build();
app.UseResponseCompression();

Now all application/json responses will be automatically GZIP-compressed.

Scaling Out with Load Balancing
Performance tuning is not enough when traffic grows. Scalability often involves distributing load across multiple servers using:

  • Horizontal Scaling : Adding more servers
  • Load Balancers : NGINX, Azure Front Door, AWS ELB, etc.

In distributed systems, session state and caching should be externalized (e.g., Redis).

Example: Configure Distributed Cache (Redis)
builder.Services.AddStackExchangeRedisCache(options =>
{
    options.Configuration = "localhost:6379";
});

public class CacheService
{
    private readonly IDistributedCache _cache;

    public CacheService(IDistributedCache cache)
    {
        _cache = cache;
    }

    public async Task SetCacheAsync(string key, string value)
    {
        await _cache.SetStringAsync(key, value, new DistributedCacheEntryOptions
        {
            AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(5)
        });
    }

    public Task<string?> GetCacheAsync(string key) => _cache.GetStringAsync(key);
}

This makes your app stateless, which is essential for load balancing.

Configure Kestrel and Hosting for High Throughput
Kestrel, the built-in ASP.NET Core web server, can handle hundreds of thousands of requests per second when configured properly.

Example: Optimize Kestrel Configuration

builder.WebHost.ConfigureKestrel(options =>
{
    options.Limits.MaxConcurrentConnections = 10000;
    options.Limits.MaxConcurrentUpgradedConnections = 1000;
    options.Limits.RequestHeadersTimeout = TimeSpan.FromSeconds(30);
});

Additionally:

  • Use reverse proxy servers (like NGINX or IIS) for static file handling and TLS termination.
  • Deploy in containerized environments for auto-scaling (e.g., Kubernetes).
  • Use Memory and Object Pooling
  • To avoid frequent object allocations and garbage collection, ASP.NET Core supports object pooling .

Example: Using ArrayPool<T>
using System.Buffers;

public class BufferService
{
    public void ProcessData()
    {
        var pool = ArrayPool<byte>.Shared;
        var buffer = pool.Rent(1024); // Rent 1KB buffer

        try
        {
            // Use the buffer
        }
        finally
        {
            pool.Return(buffer);
        }
    }
}

This approach minimizes heap allocations and reduces GC pressure — crucial for performance-sensitive applications.

Minimize Startup Time and Memory Footprint

Avoid unnecessary services in Program.cs .

Use AddSingleton instead of AddTransient where appropriate.

Trim dependencies in *.csproj files.

Example: Minimal API Setup
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddSingleton<IProductService, ProductService>();

var app = builder.Build();

app.MapGet("/products", async (IProductService service) =>
    await service.GetAllProductsAsync());

app.Run();


Minimal APIs reduce boilerplate and improve startup performance.

Monitoring and Benchmarking
You can’t improve what you don’t measure. Use tools like:
dotnet-trace and dotnet-counters

Application Insights

BenchmarkDotNet

Example: Using BenchmarkDotNet
[MemoryDiagnoser]
public class PerformanceTests
{
    private readonly ProductService _service = new();

    [Benchmark]
    public async Task FetchProducts()
    {
        await _service.GetAllProductsAsync();
    }
}

Run this benchmark to identify bottlenecks and memory inefficiencies.

Additional Optimization Tips

  • Enable HTTP/2 or HTTP/3 for better parallelism.
  • Use CDNs for static assets.
  • Employ connection pooling for database and HTTP clients.
  • Use IHttpClientFactory to prevent socket exhaustion.

builder.Services.AddHttpClient("MyClient")
.SetHandlerLifetime(TimeSpan.FromMinutes(5));

Conclusion
High performance and scalability in ASP.NET Core are achieved through a combination of asynchronous design , caching , efficient data access , and smart infrastructure choices.
By applying the strategies discussed from optimizing middleware and Kestrel configuration to leveraging Redis and compression — your ASP.NET Core application can handle massive workloads with low latency and high reliability.



European ASP.NET Core 10.0 Hosting - HostForLIFE :: OpenAPI & Minimal APIs in ASP.NET Core 10.0

clock October 6, 2025 07:41 by author Peter

Building contemporary online apps and APIs is now easier, lighter, and faster thanks to ASP.NET Core's constant evolution. Developers benefit from significant advancements in OpenAPI integration and Minimal APIs with ASP.NET Core 10.0. With the help of technologies like Swagger UI, Postman, and client SDK generators, these enhancements improve developer experience, streamline API design, and decrease boilerplate. We'll examine what's new, why it matters, and how to make the most of these improvements in this post.

1. Understanding Minimal APIs
Minimal APIs were first introduced in .NET 6 to provide a lightweight way of creating HTTP APIs without the overhead of controllers, attributes, or complex routing. Instead, you define endpoints directly in your Program.cs file.

Here’s a basic minimal API example in .NET 10:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet("/", () => "Hello, ASP.NET Core 10 Minimal APIs!");

app.Run();


Instead of controllers, the request handling logic is expressed inline. This reduces ceremony, making it ideal for:

  • Microservices
  • Prototypes and demos
  • Lightweight REST APIs

2. What’s New in Minimal APIs in .NET 10
ASP.NET Core 10 builds on the foundation of Minimal APIs with:

  • Route groups with conventions – Organize endpoints logically.
  • Improved parameter binding – Cleaner support for complex types.
  • OpenAPI (Swagger) auto-generation improvements – Richer metadata and validation.
  • SSE (Server-Sent Events) – Real-time streaming support.
  • Enhanced filters and middleware integration – Greater flexibility.

3. OpenAPI in ASP.NET Core 10
OpenAPI (formerly known as Swagger) is the industry standard for describing REST APIs. It enables:

  • Documentation: Swagger UI lets developers explore APIs interactively.
  • Client SDK generation: Auto-generate clients in C#, TypeScript, Python, etc.
  • Validation: Ensures API contracts remain consistent.

In .NET 10, Microsoft has enhanced the OpenAPI package ( Microsoft.AspNetCore.OpenApi ) to work seamlessly with Minimal APIs .

4. Setting Up OpenAPI with Minimal APIs

Add the required package in your project file ( .csproj ):
<ItemGroup>
  <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.0" />
  <PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
</ItemGroup>


Then configure it in Program.cs :
var builder = WebApplication.CreateBuilder(args);

// Add OpenAPI services
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

// Enable middleware for Swagger
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

// Define Minimal API endpoints
app.MapGet("/api/products", () =>
{
    return new[]
    {
        new Product(1, "Laptop", 1200),
        new Product(2, "Phone", 800)
    };
})
.WithName("GetProducts")
.WithOpenApi();

app.Run();

record Product(int Id, string Name, decimal Price);


Key Enhancements in .NET 10

  • .WithOpenApi() automatically generates documentation for endpoints.
  • Models ( Product ) are described in the OpenAPI schema.
  • Swagger UI displays full details without extra configuration.

5. Route Groups in Minimal APIs
.NET 10 introduces Route Groups, which make organizing endpoints easier.
var products = app.MapGroup("/api/products");

products.MapGet("/", () =>
{
    return new List<Product>
    {
        new(1, "Tablet", 500),
        new(2, "Smartwatch", 200)
    };
})
.WithOpenApi();

products.MapGet("/{id:int}", (int id) =>
{
    return new Product(id, "Generated Product", 99.99m);
})
.WithOpenApi();

  • All routes under /api/products are grouped.
  • Swagger displays them neatly under a single section.

6. OpenAPI Metadata Enrichment
You can enrich OpenAPI docs using endpoint metadata:
products.MapPost("/", (Product product) =>
{
    return Results.Created($"/api/products/{product.Id}", product);
})
.WithName("CreateProduct")
.WithOpenApi(op =>
{
    op.Summary = "Creates a new product";
    op.Description = "Adds a product to the catalog with details like name and price.";
    return op;
});

This makes the Swagger UI highly descriptive with summaries and descriptions .

7. Complex Parameter Binding
Minimal APIs now support cleaner parameter binding.
products.MapPut("/{id:int}", (int id, ProductUpdate update) =>
{
    return Results.Ok(new Product(id, update.Name, update.Price));
})
.WithOpenApi();

record ProductUpdate(string Name, decimal Price);


  • Complex request bodies like ProductUpdate are automatically parsed from JSON.
  • OpenAPI correctly documents these models.

8. Filters in Minimal APIs
Filters add cross-cutting behaviors like validation or logging without middleware.
products.MapPost("/validate", (Product product) =>
{
    if (string.IsNullOrWhiteSpace(product.Name))
        return Results.BadRequest("Name is required");

    return Results.Ok(product);
})
.AddEndpointFilter(async (context, next) =>
{
    Console.WriteLine("Before executing endpoint");
    var result = await next(context);
    Console.WriteLine("After executing endpoint");
    return result;
})
.WithOpenApi();

Filters improve reusability, and OpenAPI reflects validation details.

9. Server-Sent Events (SSE) in Minimal APIs
Streaming real-time updates is now simpler:
app.MapGet("/notifications", async context =>
{
    context.Response.Headers.Add("Content-Type", "text/event-stream");
    for (int i = 1; i <= 5; i++)
    {
        await context.Response.WriteAsync($"data: Notification {i}\n\n");
        await context.Response.Body.FlushAsync();
        await Task.Delay(1000);
    }
}).WithOpenApi();


Swagger documents the endpoint, though SSE testing is best via Postman or browsers.

10. Security with OpenAPI

You can define security schemes like JWT Bearer authentication in Swagger.
builder.Services.AddSwaggerGen(options =>
{
    options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
    {
        In = ParameterLocation.Header,
        Description = "Enter JWT with Bearer prefix",
        Name = "Authorization",
        Type = SecuritySchemeType.ApiKey
    });

    options.AddSecurityRequirement(new OpenApiSecurityRequirement
    {
        {
            new OpenApiSecurityScheme
            {
                Reference = new OpenApiReference
                {
                    Type = ReferenceType.SecurityScheme,
                    Id = "Bearer"
                }
            },
            Array.Empty<string>()
        }
    });
});


Swagger UI now includes a “Authorize” button for JWT authentication.

11. Benefits of OpenAPI & Minimal APIs in .NET 10

  • Developer Productivity: Write fewer lines of code.
  • Auto Documentation: Swagger/OpenAPI keeps docs updated.
  • Integration Ready: Generate SDKs for Angular, React, Python, etc.
  • Improved Testing: Swagger UI doubles as an interactive test client.
  • Performance: Minimal APIs are faster to start and lighter than MVC controllers.

12. Example: Full Program.cs
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

var products = app.MapGroup("/api/products");

products.MapGet("/", () =>
    new List<Product>
    {
        new(1, "Laptop", 1200),
        new(2, "Phone", 800)
    })
.WithOpenApi();

products.MapPost("/", (Product product) =>
    Results.Created($"/api/products/{product.Id}", product))
.WithOpenApi(op =>
{
    op.Summary = "Create a new product";
    op.Description = "Adds a product with name and price to the catalog.";
    return op;
});

app.Run();

record Product(int Id, string Name, decimal Price);


Conclusion
ASP.NET Core 10.0 takes Minimal APIs and OpenAPI integration to the next level. Developers can now:

  • Build lightweight APIs with minimal boilerplate.
  • Automatically generate and enrich documentation.
  • Organize endpoints better with route groups.
  • Use filters for cross-cutting concerns.
  • Stream updates via SSE.
  • Secure APIs with built-in OpenAPI security definitions.

The combination of Minimal APIs and OpenAPI in .NET 10 ensures that APIs are not only fast and efficient but also well-documented, secure, and integration-friendly. This makes ASP.NET Core 10 a powerful choice for microservices, mobile backends, and modern web APIs.



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