European ASP.NET 4.5 Hosting BLOG

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

European ASP.NET Core 9.0 Hosting - HostForLIFE :: In Clean Code, Null Coalescing vs. Null Conditional

clock February 17, 2025 07:14 by author Peter

I will illustrate Null Coalescing (??) and Null Conditional (?.) in this article. Programmers frequently struggle with null references, although contemporary languages like C# provide sophisticated solutions. Two separate but complimentary methods for creating safe and clear code are the null conditional operator (?.) and the null coalescing operator (??). This page explains how to use them, gives examples, and examines their capabilities.

What is Null Coalescing (??)?
The null coalescing operator (??) provides a fallback value when a variable is null, serving as a concise alternative to traditional null-checking if statements.

Syntax
result = variable ?? fallbackValue;

How does Null Coalescing (??) work?
If variable is not null, its value is assigned to result.
If variable is null, the fallbackValue is assigned instead.
    string userName = null;
   string displayName = userName ?? "Guest User";
   Console.WriteLine(displayName);

The null coalescing operator (??) simplifies null-checking logic.

In this example, displayName is guaranteed to have a value, even if userName is null.

This approach is more concise and readable compared to an equivalent if statement:
The traditional method to achieve this before the introduction of ??
string displayName;
if (userName != null)
{
    displayName = userName;
}
else
{
    displayName = "Guest";
}

When to use the null coalescing operator (??)

Default Values: Assign a default value when a variable is null.

Dictionary<string, string> userPreferences = new Dictionary<string, string>()
        {
            { "theme", "dark" },
            { "language", "en" }
        };

// Use ?? to provide a default value if the key doesn't exist
string theme = userPreferences.GetValueOrDefault("theme") ?? "light";
string fontSize = userPreferences.GetValueOrDefault("fontSize") ?? "medium";

Console.WriteLine($"Theme: {theme}");       // Output: Theme: dark
Console.WriteLine($"Font Size: {fontSize}"); // Output: Font Size: medium


Output

  • Theme: dark   => requested value exists in the dictionary, so it will return the same value
  • Font Size: medium  => requested values do not exist, then it will return default values provided using the null coalescing operator (??)

Chained Fallbacks: Provide multiple fallback options.
string preferredName = null;
string alternateName = null;
        
// Use ?? to check both variables and provide a default value if both are null
string displayName = preferredName ?? alternateName ?? "Unknown Person";
Console.WriteLine(displayName);  // Output: Unknown Person


Output
"Unknown Person" because both variable assigned with null value.

  • The null coalescing operator can be chained to check multiple variables.
  • The operator will return the first non-null value from the chain.
  • If all variables are null, it will return the last fallback value. In this case, "Unknown".

The traditional method to achieve multiple null checks before the introduction of ??
string preferredName = null;
string alternateName = null;

// Traditional method using if statements
string displayName;

 if (preferredName != null)
 {
     displayName = preferredName;
}
 else if (alternateName != null)
  {
     displayName = alternateName;
  }
  else
  {
     displayName = "Unknown Person";
  }

Console.WriteLine(displayName);  // Output: Unknown Person

What is Null Conditional (?.)

The null conditional operator ?. allows safe navigation of objects and their properties, avoiding null reference exceptions. It short-circuits evaluation if the object or property being accessed is null.
result = object?.Property;

How does Null Conditional (?.) work?
public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
    public Address Address { get; set; }
}

public class Address
{
    public int Id { get; set; }
    public string City { get; set; }
    public string PinCode { get; set; }
}
Person person = null;

 // Use the null conditional operator to safely access a property
 string name = person?.Name ?? "Unknown";

 Console.WriteLine(name);  // Output: Unknown

 string persionCity = person?.Address?.City ?? "London"; // If person or Address object null then it will assign default city as London
The null conditional operator (?.) is used to safely access the Name property of person. Since person is null, person?.Name will return null.
When to use Null Conditional (?.)

  • The null conditional operator (?.) allows you to safely access properties or methods of potentially null objects without throwing exceptions.
  • It can be chained to access multiple levels of properties, like person?.Address?.City.
  • It works well in scenarios where the object might be null and you want to avoid explicit null checks.

Comparing Null Coalescing (??) and Null Conditional (?.)
Null Coalescing (??)

  • Use it when you need to provide a fallback value if an expression evaluates to null.
  • It's commonly used in scenarios involving value assignment or default parameters.

Null Conditional (?.)

  • Use it when you need to safely access or call properties and methods on potentially null objects.
  • It's frequently used in deep object hierarchies or when dealing with nullable types.

Combining Both ?? and ?
Consider the example above with the Person class, which has an Address reference, and we want to use a combination of both ?? and ?. to check for null. Here's how we can implement it:
string userCity = person?.Address?.City ?? "Unknown City";
Console.WriteLine(userCity); // Output: Unknown City


Summary
In this article, we have examined how to handle null checks more efficiently by utilizing C#'s Null Coalescing (??) and Null Conditional (?.) operators. We discussed how these features can be applied to implement null checks in a cleaner, more readable manner, improving both the clarity and maintainability of the code. Additionally, we explored how to use these operators individually as well as how to combine them in a single statement to handle multiple null checks effectively, making the code more concise and eliminating the need for verbose null-checking logic.

Feel free to follow me here, and you can read more articles at this link: Click Here to explore my articles.

  • New LINQ Methods in .NET 9: Index, CountBy, and AggregateBy
  • Working with JSON in .NET Core: Newtonsoft.Json, NetJSON, and System.Text.Json
  • Implement a retry policy in .NET 6 Applications with Polly
  • Understanding Model Binding in ASP.NET Core with .NET 8
  • Data Conversions in C# with SuperConvert


European ASP.NET Core 9.0 Hosting - HostForLIFE :: How to Use Middleware for Rate Limiting in.NET?

clock February 14, 2025 06:16 by author Peter

Any application or API that is made available to the public must include rate limitation. It guards against harmful attacks including denial-of-service (DoS) attacks, guarantees equitable utilization among clients, and stops resource exhaustion. We'll go over what rate limiting is, why it's important, and how to use Visual Studio's tools to create it in.NET in this comprehensive guide.

What is Rate Limiting?
Rate limiting is the practice of controlling the number of requests a client can make to a server within a specific time period. It ensures that resources are distributed fairly and that a single client cannot overwhelm the system.

Why Implement Rate Limiting?

Here’s why rate limiting is vital.

  • Prevent System Overload: Protect your server from being overwhelmed by a flood of requests.
  • Ensure Fair Usage: Distribute resources equitably among users.
  • Mitigate Attacks: Defend against DoS attacks or API abuse.
  • Cost Control: Avoid unnecessary resource consumption, especially in cloud-based systems.
  • Improve Stability: Enhance the reliability and performance of your application.

Setting Up Rate Limiting in .NET Using Visual Studio
.NET 7 introduces a built-in rate-limiting middleware that simplifies the implementation of rate limits. Follow these detailed steps using Visual Studio to integrate this feature into your application.

Step 1. Create a New Web API Project

  • Open Visual Studio.
  • Click on Create a new project.
  • Select ASP.NET Core Web API and click Next.
  • Name your project (e.g., RateLimitingExample) and click Next.

Choose .NET 7 as the framework and click Create.
This creates a new Web API project with the required dependencies.

Step 2. Add Rate Limiting Middleware
To implement rate limiting, configure the middleware in the Program.cs file.

Open the Program.cs file.
Add rate-limiting policies to control the traffic flow. Replace the existing content with the following code.
using Microsoft.AspNetCore.RateLimiting;
using System.Threading.RateLimiting;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
// Configure rate limiting policies
builder.Services.AddRateLimiter(options =>
{
    options.AddPolicy("FixedWindowPolicy", context =>
        RateLimitPartition.GetFixedWindowLimiter(
            partitionKey: context.Connection.RemoteIpAddress?.ToString() ?? "default",
            factory: _ => new FixedWindowRateLimiterOptions
            {
                PermitLimit = 10, // Allow 10 requests
                Window = TimeSpan.FromSeconds(10), // Within 10 seconds
                QueueProcessingOrder = QueueProcessingOrder.OldestFirst,
                QueueLimit = 2 // Allow 2 requests in queue
            }));
});

var app = builder.Build();
// Use rate limiting middleware
app.UseRateLimiter();
// Map endpoints
app.MapControllers();
app.Run();


Step 3. Add a Controller

  • Right-click on the Controllers folder in Solution Explorer.
  • Select Add > Controller.
  • Choose API Controller – Empty and name it WeatherForecastController.
  • Replace the contents of the generated file with the following code.

using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
    [HttpGet]
    [EnableRateLimiting("FixedWindowPolicy")]
    public IActionResult GetWeather()
    {
        return Ok(new { Message = "Weather data retrieved successfully!" });
    }
}


This controller applies the FixedWindowPolicy rate limit to the GetWeather action.

Step 4. Test the Application

  • Press F5 or click Start to run the application.
  • Open your browser, Postman, or another API testing tool.
  • Send multiple GET requests to the endpoint:
  • http://localhost:<port>/WeatherForecast After 10 requests within 10 seconds, the API will return a 429 Too Many Requests response.

Advanced Features of Rate Limiting
The built-in middleware allows you to customize rate-limiting strategies further.

  • Sliding Window Policy: Provides smoother rate limiting by spreading limits across smaller time segments.
  • Token Bucket Policy: Allows short bursts of requests but enforces an overall rate limit.
  • Concurrency Policy: Limits the number of simultaneous requests processed by the server.

You can define these policies in the Program.cs file is similar to the fixed window example.

Consequences of Not Using Rate Limiting

Without rate limiting, your application might face.

  • Resource Exhaustion: Overloaded servers, slower response times, and potential crashes.
  • Unfair Usage: A single client can monopolize resources, leaving others without access.
  • Security Risks: Increased vulnerability to DoS attacks and brute-force attempts.
  • Higher Costs: Excessive resource consumption can drive up operational expenses.

Benefits of Using Visual Studio
Using Visual Studio to set up rate limiting provides a streamlined and integrated environment where you can.

  • Write and test code with built-in debugging tools.
  • Quickly add or manage dependencies through the NuGet Package Manager.
  • Leverage IntelliSense and code completion for error-free implementation.

Conclusion
Rate limiting is essential for building robust, secure, and scalable APIs. By using .NET’s built-in Rate Limiting Middleware and Visual Studio’s powerful tools, you can implement and test rate-limiting policies efficiently. This ensures your application is protected, performs well, and provides a fair experience for all users. Try out these steps in your project, and ensure your APIs are ready for real-world usage.



European ASP.NET Core 9.0 Hosting - HostForLIFE :: Encrypt and Decrypt Web.config Using aspnet_regiis.exe Tool

clock February 11, 2025 07:02 by author Peter

Using aspnet_regiis.exe tool to Encrypt and Decrypt Web.config Sections


Prerequisite (Deployment Server)

  • Locate the Framework Folder in the IIS Server, Ex: C:\Windows\Microsoft.NET\Framework{xx}\ v4.0.xxxxx OR v2.0.xxxxx.
  • Run the command prompt as Administrator Access,


Note. This tool (aspnet_regiis.exe) is typically found in the .NET Framework directory:

  • C:\Windows\Microsoft.NET\Framework\v4.0.xxxxx\aspnet_regiis.exe
  • C:\Windows\Microsoft.NET\Framework64\v4.0.xxxxx\aspnet_regiis.exe (for 64-bit)


Prerequisite (Local Development Machine)
Run the Developer Command Prompt for VS 20xx as Administrator Access

Commands to Execute

To Encrypt Section
> aspnet_regiis.exe -pef “<Section Name>” “<Physical Path located the Config File>”

To Decrypt Section
> aspnet_regiis.exe -pdf “<Section Name>” “<Physical Path located the Config File>”

Note
Encrypt or Decrypt Configuration Sections
    -pef <section> <physicalPath> → Encrypts a specific configuration section.

Example: aspnet_regiis -pef "appSettings" "C:\MyApp"

    -pdf <section> <physicalPath> → Decrypts a specific configuration section.

Example: aspnet_regiis -pdf " appSettings" "C:\MyApp"



European ASP.NET Core 9.0 Hosting - HostForLIFE :: Semi Auto Implemented Properties in .NET 9

clock February 7, 2025 07:59 by author Peter

C#13's Preview functionality is now semi-auto-implemented Properties. When specifying properties in class files, this feature greatly improves readability and cuts down on boilerplate code. Let's examine one straightforward situation to gain a better understanding.


Situation
Typically, an auto-implemented property is declared in C#.
public int EmplSalary { get; set; }

The compiler automatically generates a backing field like (Ex: _empSalary) and internal getter/setter methods (void set_EmplSalary(int empSalary) and int get_EmplSalary()).
However, In our real-time project cases, we need to set some custom logic such as validation, default values, computations, or lazy loading in the property’s getter or setter, we typically need to manually define the backing field.

C# 13 preview

This process is simplified by the introduction of the field keyword, which allows direct access to the backing field without the need for manual definition, as this feature is currently in the Preview stage. We have to apply the following keyword to use this in our project settings. Edit the project file by adding <LangVersion>preview</LangVersion>. So, It supports field property in project usage.

The following code gives a more illustrative idea about usage.

Before .NET 9

private int _empSalary;

/// <summary>
/// Before .NET 9
/// </summary>
public int EmpSalary
{
    get => _empSalary;
    set
    {
        if (value <= 0)
            throw new ArgumentOutOfRangeException(nameof(value),
                "Salary must be greater than 0");
        _empSalary = value;
    }
}


.NET 9 (Preview)
/// <summary>
/// In .NET 9
/// </summary>
public int EmployeeSalary
{
    get => field;
    set
    {
        if (value <= 0)
            throw new ArgumentOutOfRangeException(nameof(value),
                "Salary must be greater than 0");
        field = value;
    }
}


Benefits

  • Less Boilerplate Code: Removes the necessity for private backing fields, leading to more streamlined and concise code.
  • Enhanced Readability: Eliminates concerns about naming backing fields, as the standardized field keyword improves code clarity.
  • Property-Scoped Field: The private property field is accessible only within the property itself, ensuring better encapsulation and preventing unintended access elsewhere in the parent class. This key feature of C# 13 Semi-Auto Properties effectively mitigates a common source of errors.

Please also read Understanding UUID v7 in .NET 9 for other .NET9 related features.

Summary
This feature helps in our project's day-to-day scenarios with the benefits of Less Boilerplate Code, Enhanced Readability, and Property-Scoped Fields. As this feature is still in Preview mode, please use it with caution in our real-time projects.



European ASP.NET Core 9.0 Hosting - HostForLIFE :: Use the Authorization Option to Implement Scalar UI in.NET APIs

clock February 4, 2025 06:13 by author Peter

Microsoft declared that they would no longer include the default Swagger gen UI with any.NET API project after the release of.NET 9. In the past, Microsoft incorporated the Swagger Swashbuckle package automatically when we established a.NET API project. This package had methods like apps.UseSwagger() and app.UseSwaggerUI(). Without the need for third-party apps like Postman, these techniques demonstrated API documentation with a preset user interface for testing straight in the browser. Nevertheless,.NET 9 web API projects no longer integrate Swagger. The package hasn't been properly maintained lately, and a lot of user-reported problems are still unfixed, hence this choice was made.

Microsoft.AspNetCore is a new package developed by the Microsoft team.Similar to Swagger, OpenApi offers integrated OpenAPI documentation production. Nevertheless, this just offers JSON documentation for all endpoints and schema definitions; the browser does not display any user interface. This change's primary objective is to enable customers to utilize any UI library they choose, be it Swagger or another option. You may still add Swagger to your project and carry out all of the same tasks as before, even though Microsoft removed the default package.

Although there are a lot of Swagger substitutes out there right now, we'll talk about and use Scalar in our API project in this post. Scalar has gained popularity among developers after Swagger.

Starting a New Project

You will be prompted to configure OpenAPI support when you create new projects with.NET 9. This checkbox will register the OpenAPI service in the program and add the Microsoft.AspNetCore.OpenApi package to your project.such a cs file.

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddOpenApi();

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.MapOpenApi();
}

Now, when you run your API and navigate to /OpenApi/v1.json, it will show the documentation generated by default, which contains information about your endpoints and all the schemas you have used, as shown in the image below.

Configure Scalar.NET
First, open your package manager and install Scalar.AspNetCore.

Then, just add the app.MapScalarApiReference(); in your program.cs file to map all the API references and routes of Scalar UI. Now, if you go to /Scalar/V1, you will see a beautiful UI for your endpoints. Here, I only have one endpoint, so it looks like this.

Configure Options of Scalar
You can configure multiple options and change the settings of your UI. Some configurations include.

  • Title: Set the document title which shows on top of the browser tab
  • DarkMode: true/false to enable and disable dark mode
  • Favicon: Set the favicon of the document
  • DefaultHttpClient: Show the default HTTP client when UI loads in the browser. It shows the code implementation for the respective programming language.
  • HideModels: true/false to set whether to show model definitions
  • Layout: Set the layout/theme of Scalar UI
  • ShowSidebar: true/false to set whether to show sidebar. This only works when you have chosen the modern layout.

And many more.

Open Scalar UI by Default

You might have noticed that we have to type scalar/v1 every time in the URL to see the Scalar UI. We can change the launch URL so we don't have to do this repeatedly. Open the launchsettings.json file and add the launch URL to your profile. I have added it for both HTTP and HTTPS. You can configure it as per your requirements.

Working with Authorization and JWT Token
In most APIs, we implement JWT tokens or other types of token authentication. So, I have added a few lines of code to implement authorization using the JWT token. I have also installed Microsoft.AspNetCore.Authentication.JwtBearer package for this.
builder.Services
    .AddAuthorization()
    .AddAuthentication(x =>
    {
        x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
        x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
    })
    .AddJwtBearer(x =>
    {
        x.RequireHttpsMetadata = false;
        x.SaveToken = true;
        x.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuerSigningKey = false,
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes("your_jwt_key")),
            ValidateIssuer = false,
            ValidateAudience = false
        };
    });

app.UseAuthentication();
app.UseAuthorization();

app.MapGet("/test1", () => "This is test 1 endpoint")
    .WithName("Test1")
    .RequireAuthorization();


When I call this test1 endpoint, it gives me a 401 error (unauthorized). So, how can we resolve this? We can simply pass an auth token, but if you look at Scalar, there's no option to add an auth/bearer token on their UI. There's no option for Auth type even if I have added PreferredSecurityScheme as Bearer in MapScalarApiReference.
options.Authentication = new ScalarAuthenticationOptions
{
    PreferredSecurityScheme = "Bearer"
};


If you pass your auth token in headers with the Authorization key, it works, but that's not what we want, right? We want a similar interface to Swagger, which shows options to add tokens on the home page or in individual endpoints.

However, there is a way to achieve what we want and resolve this issue. We can use the functionality of document transformers in OpenAPI

Using this Transformer, we can inform Scalar that we want to show the Authentication option on our UI so that Scalar can add it on the home page and also in individual endpoints.

Here's the transformer class.
internal sealed class BearerSecuritySchemeTransformer : IOpenApiDocumentTransformer
{
    private readonly IAuthenticationSchemeProvider _authenticationSchemeProvider;

    public BearerSecuritySchemeTransformer(IAuthenticationSchemeProvider authenticationSchemeProvider)
    {
        _authenticationSchemeProvider = authenticationSchemeProvider;
    }

    public async Task TransformAsync(OpenApiDocument document, OpenApiDocumentTransformerContext context, CancellationToken cancellationToken)
    {
        var authenticationSchemes = await _authenticationSchemeProvider.GetAllSchemesAsync();

        if (authenticationSchemes.Any(authScheme => authScheme.Name == "Bearer"))
        {
            var requirements = new Dictionary<string, OpenApiSecurityScheme>
            {
                ["Bearer"] = new OpenApiSecurityScheme
                {
                    Type = SecuritySchemeType.Http,
                    Scheme = "bearer",
                    In = ParameterLocation.Header,
                    BearerFormat = "JWT"
                }
            };

            document.Components ??= new OpenApiComponents();
            document.Components.SecuritySchemes = requirements;

            foreach (var operation in document.Paths.Values.SelectMany(path => path.Operations))
            {
                operation.Value.Security.Add(new OpenApiSecurityRequirement
                {
                    [new OpenApiSecurityScheme
                    {
                        Reference = new OpenApiReference
                        {
                            Id = "Bearer",
                            Type = ReferenceType.SecurityScheme
                        }
                    }] = Array.Empty<string>()
                });
            }
        }
    }
}

This code will add an Authentication option on the Home page and in all request endpoints where you can pass your token to send requests.

 

This code modifies OpenAPI/Scalar documentation to show that the API supports Bearer token authentication.

  • It first checks if the API has "Bearer" authentication enabled
  • If Bearer authentication exists, it adds a security scheme in OpenAPI/Scalar
  • This security scheme tells OpenAPI/Scalar that requests should include a JWT (JSON Web Token) in the Authorization header
  • By default, this only adds support for authentication but does not require it in OpenAPI/Scalar UI
  • To make authentication look required in the UI, the code loops through all API endpoints and marks them as needing a Bearer token

 

The following loop does that,
foreach (var operation in document.Paths.Values.SelectMany(path => path.Operations))
{
    operation.Value.Security.Add(new OpenApiSecurityRequirement
    {
        [new OpenApiSecurityScheme
        {
            Reference = new OpenApiReference
            {
                Id = "Bearer",
                Type = ReferenceType.SecurityScheme
            }
        }] = Array.Empty<string>()
    });
}

This only affects the OpenAPI/Scalar UI and does not actually enforce authentication in the API. Even if the UI shows authentication as required, the API will still accept requests without a token unless it has [Authorize] or RequireAuthorization().

To apply this transformation in OpenAPI/Scalar, use the following line.
builder.Services.AddOpenApi(options =>
{
    options.AddDocumentTransformer<BearerSecuritySchemeTransformer>();
});

This ensures the security scheme and requirements are added whenever OpenAPI/Scalar documentation is generated. If you want to actually enforce authentication, you need to add [Authorize] to controllers or RequireAuthorization() in Minimal API. Now you can pass your token in this input, and it will be passed to the server without any issue, and you won't get a 401 error anymore.


I hope you like this article. If you have any questions, you can ask them in the comments, and don't forget to like and follow.



European ASP.NET Core 9.0 Hosting - HostForLIFE :: Using Bootstrap 5 Themes in ASP.NET 8

clock January 21, 2025 06:57 by author Peter

Abstract: In an ASP.NET8 MVC application, we demonstrate how to set up the use of numerous Bootstrap 5 themes. There are a lot of free Bootstrap 5 themes online that can improve the appearance of web apps.

1. The requirement for a more polished user interface
By default, the ASP.NET8 MVC project uses the Bootstrap 5 CSS UI framework. However, for some reason, the Bank application I was working on does not look very good with the default Bootstrap 5 color scheme. I therefore had to find some better Bootstrap 5 themes.

1.1. Free Bootstrap 5 themes
There are many free Bootstrap themes on the Internet. I liked the site Bootswatch [1]. Themes there are FREE, with an MIT license. I decided to use those free themes for my project. I realized, theoretically, I can even make the admin choose the theme for the app from several themes I offer preinstalled. So, I decided to make a proof-of-concept application.

2. Installing multiple Bootstrap 5 Themes
2.1. Configuration in appsetting.json

I decided to enable the web application admin to select the theme he/she prefers using the configuration option in appsettings.json.

2.2. Installing multiple themes
I downloaded several themes I liked and installed in the app.

2.3. Passing theme number to the Partial view
I defined my model and passed the info to _Layout.cshtml.
From there, I passed the info to the partial view _LoadingLayoutJsAndCss.cshtml.

In that partial view _LoadingLayoutJsAndCss.cshtml, I decide which Bootstrap theme to load based on the number configured in appsettings.json.

3. Final result
I will just show here what some themes look like in my prototype ASP.NET8 app. Please note that Theme 0 is the default Bootstrap 5 theme. It is pretty impressive how a good theme can change an app's look. The problem is that Bootstrap Theme sometimes changes not just colors but border thickness, button shape (rounded, square, etc), spacing between elements, etc. Theoretically, you need to test every dialog/form for each Bootstrap Theme you offer to users.

 

 

 

4. Concerns and Conclusion
The problem is that each theme not only changes colors but also button sizes and spacing, so theoretically, one would need to test “every form for every theme” to make sure it renders properly before delivering the product. I needed to do some work on CSS to support Themes. I needed to make sure components CSS like Breadcrumb and DataTables inherit colors from the theme. The problem is if they have color definitions in their own CSS, they will not follow the theme. You might need to do some work there.

If the project team/QA team wants to focus on only one theme, you can use the HARDCODE theme number in the release build and disable that config option. Just, I think the developers-team would need to do development in the Bootstrap default theme (0), to make sure they do not fall for some bug in the theme itself. Those themes themselves can have bugs/issues. Still, it is amazing how many quality free resources one can find for the Bootstrap UI framework.



European ASP.NET Core 9.0 Hosting - HostForLIFE :: Implement JWT Token in Net Core Api

clock January 16, 2025 07:06 by author Peter

The ASP.NET Core API's JWT (JSON Web Token) authentication provides a safe and effective method for managing user authorization and authentication. A detailed guide to configuring JWT authentication in an ASP.NET Core Web API can be found here.

Install Required NuGet Packages

Configure JWT Authentication
Update Program.cs to configure JWT authentication in the service section and middleware section.

builder.Services.AddAuthentication(opt =>
{
    opt.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    opt.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(opt =>
{   // for development only
    opt.RequireHttpsMetadata = false;
    opt.SaveToken = true;
    opt.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateIssuerSigningKey = true,
        IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(builder.Configuration["JWT:SecretKey"])),
        ValidateIssuer = true,
        ValidIssuer = builder.Configuration["JWT:Issuer"],
        ValidateAudience = true,
        ValidAudience = builder.Configuration["JWT:Audience"]
    };
});

builder.Services.AddAuthorization();

var app = builder.Build();

// Use authentication and authorization
app.UseAuthentication();
app.UseAuthorization();

app.MapControllers();

app.Run();


This configuration sets up the application to authenticate incoming requests using the JWT tokens and validate them based on certain parameters.

Generate the JWT Tokens
public string GenerateJwtToken(string userName, string name, string role)
{
    var tokenHandler = new JwtSecurityTokenHandler();
    var key = Encoding.ASCII.GetBytes(_configuration["JWT:SecretKey"]);

    var tokenDescriptor = new SecurityTokenDescriptor
    {
        Subject = new ClaimsIdentity(new Claim[]
        {
            new Claim(ClaimTypes.Name, userName),
            new Claim(ClaimTypes.GivenName, name),
            new Claim(ClaimTypes.Role, role)
        }),
        IssuedAt = DateTime.UtcNow,
        Issuer = _configuration["JWT:Issuer"],
        Audience = _configuration["JWT:Audience"],
        Expires = DateTime.UtcNow.AddMinutes(30), // can change exprires time
        SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature),
    };

    var token = tokenHandler.CreateToken(tokenDescriptor);
    var userToken = tokenHandler.WriteToken(token);

    return userToken;
}

Authenticate Users And Issue The JWT Tokens
[HttpPost("login")]
public IActionResult Login(LoginModel model)
{
    // Authenticate user
    var user = _userService.Authenticate(model.Username, model.Password);

    if (user == null)
        return Unauthorized();

    // Generate JWT token
    var token = _authenticationService.GenerateJwtToken(
        user.userName,
        user.Name,
        user.Role
    );

    return Ok(new { token });
}


Secure Your API Endpoints
Add the [Authorize] attribute to protect API endpoints. Example.
[ApiController]
[Route("api/[controller]")]
public class ProtectedController : ControllerBase
{
    [HttpGet]
    [Authorize]
    public IActionResult GetSecureData()
    {
        return Ok(new { Message = "This is a secure endpoint." });
    }
}


Test Your .NET JWT Authentication
Use a tool like Postman or cURL to test the endpoints.
First, call the /api/auth/login endpoint with valid credentials to get a token.
Use the token in the Authorization header of subsequent requests to protected endpoints:
Authorization: Bearer <your-jwt-token>

JWT token part
A JWT (JSON Web Token) consists of three parts, separated by dots (.): Header, Payload, and Signature. Here's a breakdown of these parts.

Header
The header typically consists of two fields.

  • alg: The signing algorithm used (e.g., HS256 for HMAC-SHA256).
  • typ: The type of the token, usually JWT.

{
"alg": "HS256",
"typ": "JWT"
}


Payload
The payload contains the claims. Claims are statements about the user or additional data. There are three types of claims.

  • Registered claims: Predefined claims like iss (issuer), exp (expiration), sub (subject), and aud (audience).
  • Public claims: Custom claims defined for specific use cases.
  • Private claims: Claims shared between parties that agree on them.

{
"sub": "1234567890",
"name": "peter",
"role": "Admin",
"iat": 1672545600,
"exp": 1672549200
}


Signature

The signature is used to verify the authenticity of the token and ensure that it hasn’t been tampered with.

The signature is created by,

Taking the encoded header and payload.

Concatenating them with a dot (.).
Hashing the result using the specified algorithm and a secret key.
HMACSHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
secret_key
)


Final Token format

The JWT token is the concatenation of these three parts.
<base64UrlEncodedHeader>.<base64UrlEncodedPayload>.<base64UrlEncodedSignature>

Example
JWT: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwicm9sZSI6IkFkbWluIiwiaWF0IjoxNjcyNTQ1NjAwLCJleHAiOjE2NzI1NDkyMDB9.DjKU_JB_b9PxwjU_x5U3wwtrLX7ZnZZ0mKXfTi5YYCU

Conclusion
Ultimately, we can say that authorization and authentication in.NET Core are essential to the safety and security of your application, and that using JWT authentication in.NET Core offers a reliable and secure way to authenticate users and safeguard web application resources. Data integrity and confidentiality are prioritized while.NET Core applications obtain scalability, flexibility, and interoperability with the inclusion of JWT authentication. This ensures a smooth user experience. Adopting.NET JWT authentication in.NET Core is still a crucial tactic for protecting private data and bolstering the integrity of contemporary web apps as technology advances.



European ASP.NET Core 9.0 Hosting - HostForLIFE :: Mastering [Produces("application/json")] in ASP.NET Core

clock January 10, 2025 06:32 by author Peter

If you're using ASP.NET Core to create reliable APIs, you've probably come across situations where answer format consistency is essential. It [Produces("application/json")] is useful in this situation. Let's examine its operation and the reasons it is revolutionary.

What does [Produces("application/json")] do?
It tells your API to always respond with JSON, regardless of the client’s request headers. No surprises just clean, predictable JSON responses every time.

Where and How to use It?
You can apply it at the controller or action level.
[Produces("application/json")]
[ApiController]
[Route("api/[controller]")]
public class ExampleController : ControllerBase
{
    [HttpGet]
    public IActionResult GetData()
    {
        var data = new { Message = "Hello, JSON!" };
        return Ok(data);
    }
}


What happens here?
Even if the client requests XML, your API says.
“Nope, JSON it is!”

Why use it?

  • Consistency: Ensures your API always speaks the same "language" (JSON).
  • Simplicity: Reduces unexpected behaviour caused by content negotiation.
  • Control: Guarantees the response format, no matter what the client expects.

Pro Tip
Want to support multiple formats (e.g., XML and JSON)? Use [Produces] with a list of content types.
[Produces("application/json", "application/xml")]

When to use It?

  • Use [Produces("application/json")] when.
  • Your API should always output JSON.
  • You want strict control over response formatting.
  • You’re building APIs for front-end frameworks or third-party clients that expect JSON.

In today’s API-driven world, it [Produces("application/json")] is your ally for predictable, reliable, and developer-friendly APIs. Start using it today to level up your API game.



European ASP.NET Core 9.0 Hosting - HostForLIFE :: What Does Minimal API's MapGroup Mean?

clock January 6, 2025 07:58 by author Peter

A lightweight method for creating HTTP APIs is offered by.NET Core's minimal APIs. They were first introduced in.NET 6 and improved in subsequent iterations, enabling you to process HTTP requests and construct routes with less boilerplate. MapGroup is a potent component of Minimal APIs that facilitates effective route organization and structuring.

In this article, we’ll explore.What is MapGroup?

  • Benefits of using MapGroup.
  • Pros and cons.
  • When and why to use MapGroup.
  • A practical example to showcase its use.

What is MapGroup?
MapGroup is a feature in Minimal APIs that allows you to group related endpoints together under a common route prefix and configuration. It helps in organizing endpoints logically, making your codebase more readable and maintainable.

Mapping ground in a Minimal API refers to the process of defining routes and handling requests in a streamlined manner, leveraging the simplicity of .NET's Minimal APIs. This approach allows developers to create lightweight web applications with less boilerplate code, enhancing productivity.
Example: Traditional vs. MapGroup

Without MapGroup
var app = builder.Build();

app.MapGet("/users", () => "List of users");
app.MapGet("/users/{id}", (int id) => $"User details for {id}");
app.MapPost("/users", () => "Create a new user");

app.Run();


With MapGroup

var app = builder.Build();
var usersGroup = app.MapGroup("/users");

usersGroup.MapGet("/", () => "List of users");
usersGroup.MapGet("/{id}", (int id) => $"User details for {id}");
usersGroup.MapPost("/", () => "Create a new user");

app.Run();


By using MapGroup, all endpoints under /users are grouped together, improving organization and scalability.

Key Features of MapGroup

  • Route Prefixing: Automatically applies a common prefix to all endpoints within the group.
  • Shared Middleware: Apply middleware like authentication or logging to all endpoints in a group.
  • Logical Organization: Separate concerns by grouping related endpoints (e.g., /users, /orders).

Practical Example
Here’s a complete example of using MapGroup with additional configurations.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

// Users Group
var usersGroup = app.MapGroup("/users")
                    .RequireAuthorization()
                    .WithOpenApi();

usersGroup.MapGet("/", () => "List of users");
usersGroup.MapGet("/{id:int}", (int id) => $"User details for {id}");
usersGroup.MapPost("/", () => "Create a new user");

// Orders Group
var ordersGroup = app.MapGroup("/orders")
                     .AddEndpointFilter(async (context, next) =>
                     {
                         // Example filter logic
                         Console.WriteLine("Processing order request");
                         return await next(context);
                     });

ordersGroup.MapGet("/", () => "List of orders");
ordersGroup.MapPost("/", () => "Create a new order");

app.Run();

Benefits of MapGroup

  • Clean Code Organization: MapGroup enables logical grouping of related routes, reducing clutter in your Program.cs file.
  • Shared Middleware: Apply middleware like authorization, logging, or custom filters to an entire group instead of individual endpoints.
  • Route Consistency: It automatically adds a common prefix to all routes, avoiding duplication and potential errors.
  • Scalability: As your API grows, you can easily manage and extend endpoint groups without impacting unrelated routes.
  • Enhanced Maintainability: Improves the readability of your codebase, making it easier for teams to collaborate and manage.
  • Simplicity: Minimal APIs reduce the complexity of setting up a web server.
  • Performance: They are lightweight, leading to faster response times.
  • Flexibility: Easy to modify and extend as requirements change.

Pros and Cons

Pros

  • Simplifies route definitions.
  • Reduces code duplication for common configurations.
  • Works seamlessly with middleware and filters.
  • Enhances readability and maintainability.
  • Less code to manage.
  • Quick to set up and deploy.
  • Ideal for microservices and small applications.

Cons

  • Only available in the Minimal API approach.
  • Teams accustomed to traditional controllers may face a learning curve.
  • Misconfiguration in a group could affect multiple endpoints.
  • Limited features compared to full-fledged frameworks.
  • May not be suitable for large applications requiring extensive routing and middleware.

When and Why to Use MapGroup?
When to Use
Consider using Minimal APIs when developing small to medium-sized applications, microservices, or when rapid prototyping is needed. They are particularly beneficial when you want to focus on specific functionalities without the overhead of a traditional MVC framework.

You’re building an API with Minimal APIs and need to manage multiple related routes.
You want to apply common configurations, such as authentication, to a set of routes.
Your project requires scalability, with endpoints logically organized by feature or resource.

Why Use

  • To keep your Program.cs file manageable as your API grows.
  • To improve the readability and structure of your Minimal API.
  • To enforce consistency in route prefixes and middleware usage.

mapping ground in Minimal API is a powerful approach for developers looking to create efficient and straightforward web applications in .NET.



European ASP.NET Core 9.0 Hosting - HostForLIFE :: Unit Testing in .NET Core with xUnit

clock December 17, 2024 07:24 by author Peter

Unit testing is a key component of software testing that developers can handle on their own. It is used to test the smallest components of your code. As you write your code, you may use unit tests to make sure it is working as expected or yielding the desired outcomes.

All developers benefit from testing the code before submitting it to source control. NUnit, xUnit, and other frameworks are among the many available for unit testing. We shall examine the unit testing procedure in this article.

initiative for the Net Web API. Here, we are utilizing the xUnit framework, which is a free and open-source tool, to achieve the same goal. web development. Here, we'll start by addressing the most basic functions.

Creating a Testing Project
At last, we reach the stage where our tests will require the creation of a new project. We will take advantage of the handy xUnit testing project template that comes with Visual Studio 2022 when we use it.

An open-source unit testing tool for the.NET framework called xUnit makes testing easier and frees up more time to concentrate on creating tests:

In order to inject the IEmployeeService interface into our controller during testing, we now need to construct our fictitious implementation of the interface. We are going to populate its in-memory collection with our fictitious data.
public class EmployeeServiceFake : IEmployeeService
{
    public readonly Dictionary<Guid, Employee> _employees;

    public EmployeeServiceFake()
    {
        _employees = new Dictionary<Guid, Employee>
        {
            {
                new Guid("503df499-cabb-4699-8381-d76917365a9d"),
                new Employee
                {
                    Id = new Guid("503df499-cabb-4699-8381-d76917365a9d"),
                    Name = "Name1",
                    Mno = "1234567890",
                    Salary = 36000,
                    Type = EmployeeType.Permanent
                }
            },
            {
                new Guid("77cf78a6-d6e8-4d50-afeb-39eae4567c62"),
                new Employee
                {
                    Id = new Guid("77cf78a6-d6e8-4d50-afeb-39eae4567c62"),
                    Name = "Name2",
                    Mno = "1234567890",
                    Salary = 24000,
                    Type = EmployeeType.Temporary
                }
            }
        };
    }
    public bool Exists(Guid id)
    {
        return _employees.ContainsKey(id);
    }
    public Guid Create(Employee employee)
    {
        _employees.Add(employee.Id, employee);
        return employee.Id;
    }
    public void Delete(Guid id)
    {
        _employees.Remove(id);
    }
    public List<Employee> GetAll()
    {
        return _employees.Values.ToList();
    }
    public Employee GetById(Guid id)
    {
        if (!_employees.ContainsKey(id))
        {
            return null;
        }
        return _employees[id];
    }
    public Guid Update(Employee employee)
    {
        var emp = _employees[employee.Id];
        emp.Mno = employee.Mno;
        emp.Name = employee.Name;
        emp.Type = employee.Type;
        emp.Salary = employee.Salary;
        _employees[employee.Id] = emp;
        return employee.Id;
    }
}


Write some unit tests, please! We are now prepared to write tests for our EmpController's first GetAll method.

The xUnit framework uses the [Fact] attribute, which we will use to decorate test methods to identify them as the real testing methods. In the test class, in addition to the test methods, we can have an infinite number of helper methods.

The AAA principle (Arrange, Act, and Assert) is typically followed when writing unit tests.

  • Arrange: this is the part where you usually get everything ready for the test or put another way, you get the scene ready for the test (making the objects and arranging them as needed).
  • Act: Here is where the procedure that we are testing is carried out.
  • Assert: In this last section of the test, we contrast the actual outcome of the test method's execution with our expectations.

Testing Our Actions
We will want to confirm the following in the Get method, which is the first method we are testing.

  • Whether the method yields the OkObjectResult, a response code of 200 for an HTTP request.
  • Whether the returned object includes every item in our list of Emps.

Testing the Get Method
public class EmployeeControllerTest
{
    private readonly EmployeeController _employeeController;
    private readonly IEmployeeService _employeeService;

    public EmployeeControllerTest()
    {
        _employeeService = new EmployeeServiceFake();
        _employeeController = new EmployeeController(_employeeService);
    }
    [Fact]
    public void Get_WhenCalled_ReturnsOkResult()
    {
        // Act
        var response = _employeeController.GetAll();
        // Assert
        Assert.IsType<OkObjectResult>(response as OkObjectResult);
    }
    [Fact]
    public void Get_WhenCalled_ReturnsAllItems()
    {
        // Act
        var response = _employeeController.GetAll() as OkObjectResult;
        // Assert
        var result = Assert.IsType<List<Employee>>(response.Value);
        Assert.Equal(2, result.Count);
    }
}


The class we wish to test is the one in which we create an instance of the EmployeeController object. It's crucial to remember that this constructor is called before every test method, which implies that the test is always run on a new object and the controller state is always reset.

This is crucial because, regardless of how often or in what order we run the tests, the test methods ought to be independent of one another and should yield consistent testing outcomes.

Testing the GetById Method
[Fact]
public void GetById_FakeGuidPassed_ReturnsNotFound()
{
    // Arrange
    var empId = Guid.NewGuid();
    // Act
    var response = _employeeController.GetById(empId);
    // Assert
    Assert.IsType<NotFoundResult>(response);
}
[Fact]
public void GetById_ValidGuidPassed_ReturnsOk()
{
    // Arrange
    var empId = new Guid("503df499-cabb-4699-8381-d76917365a9d");
    // Act
    var response = _employeeController.GetById(empId);
    // Assert
    Assert.IsType<OkObjectResult>(response);
}
[Fact]
public void GetById_ValidGuidPassed_ReturnsEmp()
{
    // Arrange
    var empId = new Guid("503df499-cabb-4699-8381-d76917365a9d");
    // Act
    var response = _employeeController.GetById(empId) as OkObjectResult;
    // Assert
    Assert.IsType<Employee>(response.Value);
    Assert.Equal(empId, (response.Value as Employee).Id);
}

Testing the Create Method
[Fact]
public void Create_Invalid_ReturnsBadRequest()
{
    // Arrange
    Employee? employee = null;
    // Act
    var response = _employeeController.Create(employee);
    // Assert
    Assert.IsType<BadRequestResult>(response);
}
[Fact]
public void Create_AlreadyExists_ReturnsBadRequest()
{
    // Arrange
    var employee = new Employee
    {
        Id = new Guid("503df499-cabb-4699-8381-d76917365a9d"),
        Name = "Name1",
        Mno = "1234567890",
        Salary = 36000,
        Type = EmployeeType.Permanent
    };
    // Act
    var response = _employeeController.Create(employee);
    // Assert
    Assert.IsType<BadRequestResult>(response);
}
[Fact]
public void Create_ValidEmployee_ReturnsOk()
{
    // Arrange
    var employee = new Employee
    {
        Id = Guid.NewGuid(),
        Name = "Name1",
        Mno = "1234567890",
        Salary = 36000,
        Type = EmployeeType.Permanent
    };
    // Act
    var response = _employeeController.Create(employee);
    // Assert
    Assert.IsType<CreatedAtActionResult>(response);
}
[Fact]
public void Create_ValidEmployee_ReturnsResponseItem()
{
    // Arrange
    var employee = new Employee
    {
        Id = Guid.NewGuid(),
        Name = "Name1",
        Mno = "1234567890",
        Salary = 36000,
        Type = EmployeeType.Permanent
    };
    // Act
    var response = _employeeController.Create(employee) as CreatedAtActionResult;
    var emp = response.Value as Employee;
    // Assert
    Assert.IsType<Employee>(emp);
    Assert.Equal(emp.Id, employee.Id);
}

In brief
The test scenarios for our EmployeeController are now complete, and we would like to briefly review some general unit testing guidelines. When writing unit tests, there are a few standards or best practices you should aim for. It will undoubtedly make your life easier and the life of your fellow developers if you respect these practices.

  • Readability is a must for unit tests: Nobody wants to waste time attempting to decipher the purpose of your test. Ideally, it should be evident from the test name alone.
  • Maintainability is a must for unit tests: It is our goal to write our tests so that even small modifications to the code shouldn't require us to rewrite them all. We should treat our test code the same as the production code in this situation, adhering to the DRY (don't repeat yourself) principle. This lessens the likelihood that someone will eventually reach a point where it is too difficult for them to maintain all of our tests, and they must comment them out.
  • Unit sets ought to be quick: People are likely to run tests less frequently if they take too long to complete. That is undoubtedly undesirable, as nobody wants to have to wait around for tests to finish.
  • Dependencies shouldn't exist in unit tests: It is crucial that test execution be possible for everyone involved in the project without requiring access to an outside database or system. Testing must be done in complete isolation.
  • Make tests reliable instead of just focusing on code coverage: We should feel confident that we can find errors before they are introduced into the production system thanks to well-designed tests. It is simple to write tests that pass and have more code coverage by omitting certain assertions. However, there's no use in doing that. When it comes time to modify the code, we should make an effort to test the appropriate things so that we can rely on them.

In summary
This article has taught us the definition of unit testing and how to set up an xUnit project for unit testing. The fundamental scenarios for testing the controller logic on a few CRUD operations have also been taught to us. You should find these examples to be a great place to start when creating your own unit tests and testing larger, more intricate projects. Thank you for reading, and hopefully, this post will help you understand ASP.NET Core unit testing and concepts a little bit better. We learned the new technique and evolved together. Happy coding!



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