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 :: Rate Limiting and Throttling in ASP.NET Core Web API

clock September 15, 2025 08:22 by author Peter

Thousands of requests per second are frequently made to APIs. Excessive traffic, whether malicious (DoS/DDoS) or accidental (clients flooding with requests), can cause system failure, raise expenses, or impair performance if sufficient controls are not in place. Techniques like rate limitation and throttling are essential for managing API usage, guaranteeing equitable resource allocation, and safeguarding backend services.


This post will explain how to use built-in middleware (from.NET 7+), bespoke solutions, and recommended practices to establish rate restriction in ASP.NET Core Web APIs.

What is rate limiting?
Rate limiting defines how many requests a client (IP, user, or token) can make in a given time window.

For example

  • Limit: 100 requests per minute per client.
  • If exceeded, the API returns HTTP 429 Too Many Requests.


What is throttling?
Throttling goes beyond rate limiting. Instead of outright rejecting requests, it can:

  • Queue or delay requests until capacity is available.
  • Reduce service quality for heavy users while maintaining fairness.
  • Apply dynamic limits based on client type (free vs. premium).

Benefits of Rate Limiting & Throttling

  • Prevent abuse (scraping, brute-force attacks).
  • Protect backend systems from overload.
  • Ensure fair use among consumers.
  • Support tiered plans (e.g., free users: 50 requests/min, premium: 500 requests/min).

Implementing Rate Limiting in ASP.NET Core
1. Using .NET 7+ Built-in Rate Limiting Middleware

ASP.NET Core 7 introduced a dedicated rate-limiting middleware.

Install Package
If you’re on .NET 7+:
dotnet add package Microsoft.AspNetCore.RateLimiting

Configure in Program.cs
using System.Threading.RateLimiting;
using Microsoft.AspNetCore.RateLimiting;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRateLimiter(options =>
{
    // Limit each client to 100 requests per minute
    options.AddFixedWindowLimiter("Fixed", opt =>
    {
        opt.PermitLimit = 100;
        opt.Window = TimeSpan.FromMinutes(1);
        opt.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
        opt.QueueLimit = 2; // Max queued requests
    });
});

var app = builder.Build();

app.UseRateLimiter();

app.MapGet("/api/data", () => "This is a rate-limited endpoint")
   .RequireRateLimiting("Fixed");

app.Run();


2. Token Bucket Limiter Example
This allows burst traffic while enforcing overall limits.
options.AddTokenBucketLimiter("TokenBucket", opt =>
{
    opt.TokenLimit = 50;                 // Max tokens
    opt.QueueLimit = 2;
    opt.ReplenishmentPeriod = TimeSpan.FromSeconds(10);
    opt.TokensPerPeriod = 10;            // Refill rate
    opt.AutoReplenishment = true;
});


3. Sliding Window Limiter Example
Smooths out spikes by distributing requests across sliding intervals.
options.AddSlidingWindowLimiter("SlidingWindow", opt =>
{
    opt.PermitLimit = 100;
    opt.Window = TimeSpan.FromMinutes(1);
    opt.SegmentsPerWindow = 6; // 10 sec segments
    opt.QueueLimit = 2;
});

4. Per-User or Per-API Key Limiting
You can bind rate limits to users, API keys, or IPs.
builder.Services.AddRateLimiter(options =>
{
    options.GlobalLimiter = PartitionedRateLimiter.Create<HttpContext, string>(httpContext =>
    {
        var userId = httpContext.User?.Identity?.Name ?? "anonymous";
        return RateLimitPartition.GetFixedWindowLimiter(userId, _ => new FixedWindowRateLimiterOptions
        {
            PermitLimit = 10,
            Window = TimeSpan.FromSeconds(30)
        });
    });
});


Handling 
Exceeded Limits
When a client exceeds the allowed requests, ASP.NET Core automatically returns:
HTTP/1.1 429 Too Many Requests
Retry-After: 60

You can customize the response:
options.OnRejected = (context, token) =>
{
    context.HttpContext.Response.StatusCode = StatusCodes.Status429TooManyRequests;
    return context.HttpContext.Response.WriteAsync("Too many requests. Please try again later.");
};


Implementing Throttling (Delaying Requests)
Instead of rejecting requests, you can queue and delay them.
options.AddFixedWindowLimiter("Throttle", opt =>
{
    opt.PermitLimit = 5;
    opt.Window = TimeSpan.FromSeconds(10);
    opt.QueueLimit = 5;
    opt.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
});


Here, extra requests wait in a queue instead of failing immediately.

Best Practices for Rate Limiting

  • Apply limits per identity, not globally (use API key, user, or IP).
  • Different plans for different clients (free vs. premium tiers).
  • Monitor & log 429 responses to detect abuse.
  • Return Retry-After headers so clients can back off.
  • Combine with API Gateway (e.g., YARP, NGINX, Azure API Management) for distributed systems.
  • Always test under load scenarios to fine-tune values.

Example: Full ASP.NET Core Web API with Rate Limiting
using System.Threading.RateLimiting;
using Microsoft.AspNetCore.RateLimiting;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();
builder.Services.AddRateLimiter(options =>
{
    options.AddFixedWindowLimiter("ApiLimiter", opt =>
    {
        opt.PermitLimit = 100;
        opt.Window = TimeSpan.FromMinutes(1);
        opt.QueueLimit = 0;
    });

    options.OnRejected = async (context, _) =>
    {
        context.HttpContext.Response.StatusCode = 429;
        await context.HttpContext.Response.WriteAsync("Too many requests. Slow down!");
    };
});

var app = builder.Build();

app.UseHttpsRedirection();
app.UseAuthorization();

app.UseRateLimiter();

app.MapControllers().RequireRateLimiting("ApiLimiter");

app.Run();


Conclusion
Rate limiting and throttling are essential to keep your ASP.NET Core Web API secure, stable, and fair. With .NET 7’s built-in middleware, you can easily configure fixed, sliding, or token bucket rate limits. For advanced needs, combine them with per-user throttling, API gateways, and monitoring to maintain performance and reliability.



European ASP.NET Core 9.0 Hosting - HostForLIFE :: Stopping Cookie Theft and Session Hijacking in ASP.NET Core

clock September 11, 2025 08:35 by author Peter

Cookies are frequently used by web applications to preserve user sessions following authentication. However, attackers can assume user identities and obtain illegal access if cookies are stolen or compromised. Two of the most prevalent attack methods in contemporary online applications are session hijacking and cookie theft. The recommended methods for preventing session hijacking in ASP.NET Core will be discussed in this post.

What is session hijacking?

  • Session hijacking is when an attacker takes over a valid session by stealing session cookies. This can be done via:
  • XSS (Cross-Site Scripting) → Injecting malicious JavaScript to steal cookies
  • Packet Sniffing → Intercepting cookies over insecure HTTP connections
  • Session Fixation → Forcing a user to use a known session ID
  • Man-in-the-Middle Attacks → Capturing cookies during transmission

Once an attacker gets hold of a session cookie, they can act as a legitimate user.

ASP.NET Core Built-in Protections

ASP.NET Core provides mechanisms to secure cookies and reduce hijacking risks. Let’s see how to configure them.

1. Use Secure Cookies

Ensure cookies are only sent over HTTPS and not accessible via JavaScript.
builder.Services.ConfigureApplicationCookie(options =>
{
    options.Cookie.HttpOnly = true; // Prevent JavaScript access
    options.Cookie.SecurePolicy = CookieSecurePolicy.Always; // HTTPS only
    options.Cookie.SameSite = SameSiteMode.Strict; // Prevent CSRF
});


Best Practice: Always enforce HTTPS using app.UseHttpsRedirection();.

2. Short Session Lifetimes with Sliding Expiration
Short-lived cookies minimize the attack window.
builder.Services.ConfigureApplicationCookie(options =>
{
    options.ExpireTimeSpan = TimeSpan.FromMinutes(20);
    options.SlidingExpiration = true; // Refresh on activity
});

3. Regenerate Session IDs on Login
Prevent session fixation by regenerating identifiers after login.
await _signInManager.SignInAsync(user, isPersistent: false);
await _context.SaveChangesAsync();


ASP.NET Core Identity automatically issues a new cookie upon sign-in, mitigating fixation attacks.

4. Implement Cookie Authentication Validation
Periodically validate security stamps to invalidate stolen cookies.
builder.Services.Configure<SecurityStampValidatorOptions>(options =>
{
    options.ValidationInterval = TimeSpan.FromMinutes(5);
});


This ensures that if a user changes their password or logs out, old cookies become invalid.

5. Use SameSite Cookies Against CSRF
SameSite prevents cookies from being sent in cross-site requests.
options.Cookie.SameSite = SameSiteMode.Strict;

If your app requires cross-site cookies (e.g., external login providers), consider SameSite=Lax but avoid None unless absolutely necessary (and always use HTTPS).

6. Protect Against XSS (Cross-Site Scripting)
Since XSS is a common way to steal cookies:

  •     Encode all output (@Html.Encode() or Razor automatic encoding).
  •     Use Content Security Policy (CSP).
  •     Sanitize user inputs.

In Program.cs:
app.Use(async (context, next) =>
{
    context.Response.Headers.Add("Content-Security-Policy", "default-src 'self'");
    await next();
});


7. Enforce Re-authentication for Sensitive Actions
For critical operations (password change, payment, deleting account), force users to re-enter credentials or MFA.
var user = await _signInManager.GetTwoFactorAuthenticationUserAsync();
if (user == null)
{
    return RedirectToAction("Login");
}


8. Use Multi-Factor Authentication (MFA)
Even if cookies are stolen, requiring a second factor makes hijacking much harder.

9. Monitor and Revoke Compromised Sessions
Log user login locations, devices, and IPs. Allow users (and admins) to view and revoke active sessions.
await _signInManager.SignOutAsync(); // Invalidate cookie

Conclusion
Session hijacking and cookie theft are real threats, but ASP.NET Core provides strong tools to mitigate them.
To secure your app:

  • Always use HTTPS with secure, HttpOnly, and SameSite cookies.
  • Shorten cookie lifetimes and use sliding expiration.
  • Regenerate session IDs after login and validate security stamps.
  • Defend against XSS and CSRF attacks.
  • Enforce MFA and re-authentication for sensitive operations.

By combining these techniques, you can significantly reduce the attack surface and protect your users.



European ASP.NET Core 9.0 Hosting - HostForLIFE :: Using ASP.NET Core to Guard Against Malformed Payloads and JSON Injection

clock September 8, 2025 07:47 by author Peter

JSON injection: what is it?

  • When an attacker modifies a JSON payload's structure to add unexpected keys, values, or scripts, this is known as JSON injection.
  • Attackers take advantage of
    • Additional fields (such as isAdmin: true).
    • JSON string script injection (which, if done incorrectly, can result in XSS).
    • JSON was altered to avoid validations or to cause parser crashes.

An example of an attack payload

Example Attack Payload
{
"username": "attacker",
"email": "[email protected]",
"isAdmin": true,        // Sensitive field injection
"__proto__": { "polluted": "yes" } // Prototype pollution attack
}


If your API model-binds this blindly into your entity, attackers can escalate privileges or poison objects.

Risks of Malformed JSON

  • Denial of Service (DoS): Sending enormous JSON payloads.
  • Deserialization flaws: Exploiting weak parsers (e.g., type confusion).
  • Validation bypass: Sending unexpected JSON structures.

How to Protect in ASP.NET Core?

1. Use DTOs Instead of Entities

Never accept raw JSON into entity models. Define Data Transfer Objects (DTOs) with strict fields.
public class RegisterDto
{
[Required, StringLength(50)]
public string Username { get; set; }

[Required, EmailAddress]
public string Email { get; set; }

[Required, StringLength(100)]
public string Password { get; set; }
}


Controller
[HttpPost("register")]
public IActionResult Register([FromBody] RegisterDto dto)
{
if (!ModelState.IsValid)
    return BadRequest(ModelState);

// Safe mapping
var user = new User
{
    Username = dto.Username,
    Email = dto.Email,
    IsAdmin = false // Explicitly controlled
};

return Ok(user);
}


Prevents attackers from injecting extra JSON properties, such as isAdmin.

2. Reject Unknown Properties

By default, System. Text.Json ignores unknown fields. Force it to fail on unknown JSON properties.
builder.Services.AddControllers()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.ReadCommentHandling = JsonCommentHandling.Disallow;
options.JsonSerializerOptions.AllowTrailingCommas = false;
options.JsonSerializerOptions.UnknownTypeHandling = System.Text.Json.Serialization.JsonUnknownTypeHandling.Fail;
options.JsonSerializerOptions.PropertyNameCaseInsensitive = false;
});


Or, in Newtonsoft.Json.
builder.Services.AddControllers()
.AddNewtonsoftJson(options =>
{
options.SerializerSettings.MissingMemberHandling = Newtonsoft.Json.MissingMemberHandling.Error;
});


Any unexpected JSON field will cause a 400 Bad Request.

3. Input Validation

Use Data Annotations or FluentValidation to validate JSON payloads.
if (!ModelState.IsValid)
return BadRequest(ModelState);


Ensures malformed JSON (wrong type, missing field) gets rejected.

4. Limit Request Size (Prevent DoS)

Attackers may send gigantic JSON payloads to crash your server. Set max request body size.
app.Use(async (context, next) =>
{
context.Request.Headers.ContentLength = Math.Min(context.Request.ContentLength ?? 0, 10_000); // 10 KB
await next();
});

Or in Kestrel
builder.WebHost.ConfigureKestrel(options =>
{
options.Limits.MaxRequestBodySize = 10 * 1024; // 10 KB
});

Protects against payload flooding.

5. Sanitize JSON String Fields

Attackers may inject <script> or SQL-like payloads inside JSON strings. Use HtmlSanitizer or encoding before saving.
var sanitizer = new HtmlSanitizer();
dto.Username = sanitizer.Sanitize(dto.Username);


Prevents XSS when storing/displaying JSON fields.
6. Strong Content-Type Validation
Reject requests that are not application/json.

if (!context.Request.ContentType?.Contains("application/json") ?? true)
{
context.Response.StatusCode = StatusCodes.Status415UnsupportedMediaType;
return;
}


Stops attackers from sneaking payloads with wrong MIME types.
7. Use JsonDocument for Strict Parsing
If you don’t trust the payload at all, parse manually.
using var doc = JsonDocument.Parse(jsonString, new JsonDocumentOptions
{
AllowTrailingCommas = false,
CommentHandling = JsonCommentHandling.Disallow
});

if (!doc.RootElement.TryGetProperty("username", out var username))
return BadRequest("Missing username");


Complete control over parsing logic.

8. Audit & Logging

Log rejected payloads with correlation IDs.
_logger.LogWarning("Invalid JSON payload received: {Payload}", jsonString);

Helps detect attack attempts.

Best Practices Checklist

  • Use DTOs (never bind entities).
  • Fail on unknown JSON properties.
  • Validate input with Data Annotations/FluentValidation.
  • Set max request body size to prevent DoS.
  • Sanitize string fields for XSS safety.
  • Enforce application/json Content-Type.
  • Parse manually ( JsonDocument ) for untrusted payloads.
  • Log and monitor invalid payload attempts.

Conclusion
ASP.NET Core provides strong defenses, but developers must explicitly enable strict JSON parsing and validation.
By using DTOs, rejecting unknown fields, sanitizing input, and setting request limits, you protect your API from.

  • JSON Injection
  • Malformed Payload DoS
  • Prototype Pollution
  • XSS inside JSON


European ASP.NET Core 9.0 Hosting - HostForLIFE :: Utilizing a Secure API to Verify UPI IDs

clock September 4, 2025 08:14 by author Peter

To guarantee accuracy and lower failure rates in digital payment systems, a UPI (Unified Payments Interface) ID must be validated before a transaction is started. Without revealing any critical implementation details, this article describes how to integrate a UPI ID validation API using JavaScript and C# (ASP.NET). To demonstrate, we'll use a fictitious endpoint.

Why Validate UPI IDs?

  • Avoid transaction failures due to incorrect UPI IDs
  • Improve user experience by providing real-time feedback
  • Ensure the UPI ID belongs to the correct customer

Technologies Used

  • C# (ASP.NET WebForms/Backend)
  • JavaScript (AJAX for frontend calls)
  • JSON for data communication
  • Dummy API endpoint (replace with actual provider)

Example API Request
POST https://dummyapi.example.com/v1/payments/validate/vpa
Content-Type: application/json
{
"vpa": "user123@dummyupi"
}


Successful Response
{
  "vpa": "user123@dummyupi",
  "customer_name": "John Doe",
  "success": true
}


Invalid UPI Response
{
  "error": {
    "code": "BAD_REQUEST_ERROR",
    "description": "Invalid VPA. Please enter a valid Virtual Payment Address",
    "source": "customer",
    "step": "payment_initiation",
    "reason": "invalid_vpa"
  }
}


Backend Implementation (C#)
Here’s a simplified C# function to validate a UPI ID via HTTP POST.
public static string ValidateUPIID(string upi)
{
string responseJson = "";
try
{
    var requestObj = new { vpa = upi };
    string requestJson = new JavaScriptSerializer().Serialize(requestObj);

    HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://dummyapi.example.com/v1/payments/validate/vpa");
    request.Method = "POST";
    request.ContentType = "application/json";

    byte[] data = Encoding.UTF8.GetBytes(requestJson);
    using (var stream = request.GetRequestStream())
    {
        stream.Write(data, 0, data.Length);
    }

    using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
    using (StreamReader reader = new StreamReader(response.GetResponseStream()))
    {
        responseJson = reader.ReadToEnd();
    }

    if (responseJson.Contains("success"))
    {
        var jsonObj = new JavaScriptSerializer().Deserialize<UPIResponse>(responseJson);
        return jsonObj.success ? $"success - {jsonObj.customer_name}" : "failed - ";
    }
    else if (responseJson.Contains("error"))
    {
        var errorObj = new JavaScriptSerializer().Deserialize<UPIErrorResponse>(responseJson);
        string errDesc = !string.IsNullOrEmpty(errorObj.error.description) ? errorObj.error.description : "Invalid VPA";
        string errReason = !string.IsNullOrEmpty(errorObj.error.reason) ? errorObj.error.reason : "invalid_vpa";
        return $"reason - {errDesc} - {errReason}";
    }

    return "failed - unknown error";
}
catch (Exception ex)
{
    return "error - " + ex.Message;
}
}


public class UPIResponse
{
public string vpa { get; set; }
public string customer_name { get; set; }
public bool success { get; set; }
}
public class UPIErrorResponse
{
public UPIError error { get; set; }
}
public class UPIError
{
public string code { get; set; }
public string description { get; set; }
public string source { get; set; }
public string step { get; set; }
public string reason { get; set; }
}

JavaScript Frontend (AJAX Call)
<div class="bid-content-common bid-content-3">
<label class="upiid-lble">UPI ID</label>
<input id="txtupiid" runat="server" type="text" placeholder="Enter the UPI ID"
       onchange="UPIIDtxtboxchanges()" onblur="handleBlur()" />
<span id="upidtxt"></span>
<input id="upidvalidation" type="hidden" />
<button id="applybtn">Apply</button>
</div>

<script>
function UPIIDtxtboxchanges() {
    var applybtn = document.getElementById("applybtn");
    var upitxt = document.getElementById("upidvalidation");
    var txtbutton = document.getElementById("txtupiid");
    var verifytxt = document.getElementById("upidtxt");

    upitxt.value = 'Verify';
    upitxt.style.backgroundColor = "#F0F0F0";
    upitxt.style.border = "2px solid #979F6E";
    upitxt.style.color = "black";
    verifytxt.innerText = "";
    applybtn.style.pointerEvents = "auto";
}

function handleBlur() {
    // Assuming upivalidationmethod takes a callback function
    upivalidationmethod(function (isValid) {
        if (isValid) {
            return true;
        } else {
            return false;
        }
    });
}

function upivalidationmethod(callback) {
    var upiId = document.getElementById("upiInput").value;

    $.ajax({
        type: "POST",
        url: "/your-page.aspx/ValidateUPI",
        contentType: "application/json; charset=utf-8",
        data: JSON.stringify({ upi: upiId }),
        success: function (res) {
            var status = res.d.split('-');
            if (status[0] === "success") {
                $("#message").text("Valid UPI: " + status[1]).css("color", "green");
                callback(true);
            } else {
                $("#message").text("Invalid UPI").css("color", "red");
                callback(false);
            }
        },
        error: function () {
            $("#message").text("Error validating UPI").css("color", "red");
            callback(false);
        }
    });
}
</script>


Best Practices

  • Always encrypt sensitive credentials used in API headers.
  • Validate and sanitize inputs to avoid injection or malformed requests.
  • Log and monitor UPI validation failures for system analysis.

Conclusion
Including a UPI ID validation phase in your application guarantees a better user experience, fewer unsuccessful transactions, and more seamless payments. This procedure is made more efficient by using an API, which provides error handling and real-time customer name checks. Securely in production, substitute your real provider's information with the fake API URL and login credentials.



European ASP.NET Core 9.0 Hosting - HostForLIFE :: Blazor Cheatsheet: An Easy-to-Use Guide

clock September 1, 2025 10:12 by author Peter

Blazor is a web framework developed by Microsoft that allows developers to build interactive web applications using C# instead of JavaScript. It is part of the .NET ecosystem, making it possible to run C# code directly in the browser with the help of WebAssembly, or on the server with a real-time connection. This cheatsheet is a quick guide to the most critical Blazor features, syntax, and usage examples.

Blazor Hosting Models
Blazor Server

  •     Runs on the server.
  •     Uses SignalR to update UI.
  •     Small download size.

Example
@page "/counter"
<h3>Counter</h3>
<p>Count: @count</p>
<button @onclick="Increment">Click</button>

@code {
    private int count = 0;
    private void Increment() => count++;
}


Important: Faster load, but requires a constant connection.

Blazor WebAssembly

  • Runs in the browser.
  • Uses WebAssembly to execute .NET code.
  • Larger download size.
  • Important: Works offline after first load.

Components
Small building blocks of UI.
Written in .razor files.
Example
@code {
    [Parameter] public string Title { get; set; }
}

<h3>@Title</h3>

Important: Use [Parameter] for parent-to-child data.

Data Binding
1. One-way binding
<p>Hello, @name</p>
@code {
    string name = "Peter";
}


Data flows from code to UI.

2. Two-way binding

<input @bind="name" />
<p>@name</p>

@code {
    string name = "Peter";
}

Data syncs between UI and code.

Event Handling

Use @on... attributes.

Example
<button @onclick="ShowMessage">Click</button>

@code {
    void ShowMessage() => Console.WriteLine("Clicked!");
}


Lifecycle Methods

Special methods that control component behavior.

Common ones
protected override void OnInitialized() { }
protected override void OnParametersSet() { }
protected override async Task OnAfterRenderAsync(bool firstRender) { }


Important

  •     OnInitialized: Runs when the component is created.
  •     OnParametersSet: Runs when the parent sends new data.
  •     OnAfterRenderAsync: Runs after rendering UI.

Dependency Injection
Services can be injected into components.

Example
@inject HttpClient Http

<button @onclick="GetData">Fetch Data</button>

@code {
    string data;
    async Task GetData() {
        data = await Http.GetStringAsync("https://api.example.com/data");
    }
}

Important: Register services in the Program.cs file.

Routing

Define a route with @page.

Example
    @page "/about"
    <h3>About Page</h3>


For navigation
<NavLink href="/about">Go to About</NavLink>

Forms and Validation

Use EditForm with models.

Example
    @page "/form"
    <EditForm Model="user" OnValidSubmit="HandleValidSubmit">
        <InputText @bind-Value="user.Name" />
        <ValidationMessage For="@(() => user.Name)" />
        <button type="submit">Submit</button>
    </EditForm>

    @code {
        User user = new();
        void HandleValidSubmit() => Console.WriteLine("Submitted!");
        class User { public string Name { get; set; } }
    }

State Management

  •     Local state (inside component): Use fields/properties.
  •     App-wide state: Use services registered as Scoped.

JavaScript Interop

Call JS from C# or vice versa.
    Example

    @inject IJSRuntime JS

    <button @onclick="CallJS">Run JS</button>

    @code {
        async Task CallJS() {
            await JS.InvokeVoidAsync("alert", "Hello from Blazor");
        }
    }

Reusable Layouts
Use MainLayout.razor.

Example
    @inherits LayoutComponentBase
    <div class="page">
        <div class="sidebar">Menu</div>
        <div class="content">@Body</div>
    </div>

Important: @Body This is where the child page renders.

Error Handling
Use try-c
atch in methods.
    Example
    try {
        await Http.GetStringAsync("bad-url");
    } catch (Exception ex) {
        Console.WriteLine(ex.Message);
    }


Conclusion
Blazor gives developers the ability to use C# rather than JavaScript to construct cutting-edge online applications. Blazor offers the full.NET ecosystem to web development with features including components, data binding, routing, forms, dependency injection, and JavaScript interop. The most important ideas for getting started and creating scalable apps more quickly are covered in this cheat sheet.



European ASP.NET Core 9.0 Hosting - HostForLIFE :: ASP.NET Core Web API Security Using JWT Authentication

clock August 29, 2025 09:07 by author Peter

Mobile apps, SaaS platforms, IoT devices, and business systems are all powered by APIs, which form the foundation of today's digital economy.  However, a significant obstacle that comes with their popularity is security.  

APIs are one of the most popular attack vectors for cybercriminals, according to OWASP, and are frequently taken advantage of through compromised authentication, lax authorization, or data exposure. With the help of a real-world example—a bookstore API—we will walk through the entire process of securing an ASP.NET Core Web API using role-based authorization and JWT authentication in this post.

Why API Security Matters?
Imagine a bookstore API that exposes endpoints to manage books, authors, and sales. Without security:

  • Anyone could list books, update prices, or delete data.
  • Hackers could steal sensitive reports intended for admins only.
  • Attackers could flood the API with requests, causing downtime.

That’s why API security is non-negotiable.

Common API Security Threats

Before jumping into implementation, let’s recall the top threats (from OWASP API Top 10):

  1. Broken Authentication: Weak login mechanisms or missing tokens.
  2. Broken Authorization: Users accessing data or endpoints they shouldn’t.
  3. Injection Attacks (SQL, NoSQL, Command): Malicious input executed by the system.
  4. Sensitive Data Exposure: Sending unencrypted or excessive data.
  5. Rate Limiting & DoS Attacks – Flooding APIs with requests.
  6. Improper Logging & Monitoring – No visibility into attacks.

Best Practices for API Security
To mitigate these threats, adopt a defense-in-depth approach:

  • Use HTTPS everywhere—no plain HTTP.
  • Authentication & Authorization —JWT or OAuth 2.0 with RBAC/Policies.
  • Validate Inputs —prevent SQL injection and NoSQL injection.
  • Rate Limiting & Throttling —prevent abuse and DoS attacks.
  • Centralized Secret Management —Azure Key Vault or AWS Secrets Manager.
  • Error Handling —don’t leak stack traces.
  • Monitoring & Logging —track security events with Serilog or App Insights.

Implementation: Securing a Bookstore API with JWT
We’ll now build a secure Bookstore API in ASP.NET Core Web API with:

  • JWT-based authentication
  • Role-based authorization (admin vs. user)
  • Secure endpoints for books and admin reports

Step 1. Create Project
dotnet new webapi -n BookstoreApi
cd BookstoreApi


Step 2. Add NuGet Package
dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer

Step 3. Configure Authentication & Authorization ( Program.cs )
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Text;

var builder = WebApplication.CreateBuilder(args);

// Add Authentication with JWT
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            ValidIssuer = "https://api.bookstore.com",
            ValidAudience = "https://api.bookstore.com"
            IssuerSigningKey = new SymmetricSecurityKey(
                Encoding.UTF8.GetBytes("SuperSecretKey12345")) // use Key Vault in production
        };
    });

// Authorization Policies
builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("AdminOnly", policy => policy.RequireRole("Admin"));
});

builder.Services.AddControllers();

var app = builder.Build();

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

app.MapControllers();

app.Run();


Step 4. Create Auth Controller ( Controllers/AuthController.cs )
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;

namespace BookstoreApi.Controllers
{
    [ApiController]
    [Route("api/[controller]")]
    public class AuthController : ControllerBase
    {
        [HttpPost("login")]
        public IActionResult Login(string username, string password)
        {
            // Demo validation (replace with ASP.NET Identity or DB check in production)
            if (username == "admin" && password == "password")
            {
                var claims = new[]
                {
                    new Claim(ClaimTypes.Name, username),
                    new Claim(ClaimTypes.Role, "Admin")
                };

                var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("SuperSecretKey12345"));
                var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

                var token = new JwtSecurityToken(
                    issuer: "https://api.bookstore.com",
                    audience: "https://api.bookstore.com",
                    claims: claims,
                    expires: DateTime.Now.AddMinutes(30),
                    signingCredentials: creds);

                return Ok(new { token = new JwtSecurityTokenHandler().WriteToken(token) });
            }

            return Unauthorized();
        }
    }
}

Step 5. Create Secure Data Controller ( Controllers/SecureDataController.cs )
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace BookstoreApi.Controllers
{
    [ApiController]
    [Route("api/[controller]")]
    public class SecureDataController : ControllerBase
    {
        // Accessible by any authenticated user
        [HttpGet("books")]
        [Authorize]
        public IActionResult GetBooks() =>
            Ok("List of available books. (Authenticated users only)");

        // Accessible only by Admin role
        [HttpGet("admin/reports")]
        [Authorize(Policy = "AdminOnly")]
        public IActionResult GetAdminReports() =>
            Ok("Sensitive sales reports. (Admins only)");
    }
}

Testing the API
Log in to get a JWT token
POST https://api.bookstore.com/api/auth/login
Body: { "username": "admin", "password": "password" }

Response
{ "token": "eyJhbGciOiJIUzI1NiIsIn..." }

Access books endpoint. (user-protected)
GET https://api.bookstore.com/api/securedata/books
Authorization: Bearer <token>


Access admin reports endpoint (admin-only)
GET https://api.bookstore.com/api/securedata/admin/reports
Authorization: Bearer <token>


Enhancing Security Further

  • Store SuperSecretKey12345 in Azure Key Vault or AWS Secrets Manager.
  • Use the AspNetCoreRateLimit NuGet package to apply rate limiting.
  • Enforce HTTPS redirection
    • app.UseHttpsRedirection();
  • Monitor API usage with Serilog and Application Insights.
  • Regularly patch dependencies and update the .NET runtime.

Conclusion
API security is not just about authentication; it’s a multi-layered defense strategy. In this article, we:

  • Reviewed the OWASP API Top 10 threats.
  • Implemented JWT authentication in ASP.NET Core.
  • Applied role-based authorization for sensitive endpoints.
  • Discussed enterprise-grade enhancements like rate limiting and secret management.

With these practices, your ASP.NET Core Web APIs will be secure, reliable, and production-ready.



European ASP.NET Core 9.0 Hosting - HostForLIFE :: How to Print PDF Documents in C# (Tutor for Developers)?

clock August 26, 2025 07:43 by author Peter

It is frequently necessary to print PDF documents programmatically when working with corporate or enterprise applications. Whether it's shipping labels, bills, reports, or hiring-related business icons, developers frequently require a dependable method of sending PDFs straight to printers without the need for user input. Third-party libraries are typically needed to handle PDF printing reliably in.NET settings. IronPrint, a small and developer-friendly library made to make C# document printing easy, is one example of such a tool.


 We'll examine IronPrint in this post, discover how it functions, and view a comprehensive example of printing a PDF file in C#.

How to Print PDF in C# Using IronPrint?

  • Create a new Console application Project using Visual Studio.
  • Install IronPrint Nugget using Nugget package manager
  • Print PDF files using the IronPrint library.
  • Printer Settings

Introduction to IronPrint
IronPrint .NET printing library developed by Iron Software. It provides a straightforward API for printing PDF files and images without needing Adobe Acrobat or any third-party print drivers installed. Some of its key features include.

  • Direct printing of PDF, images, and multi-page documents, and print multiple PDF files. Also, it allows printing PDF files programmatically.
  • Control over print settings like printer selection, duplex, paper size, and copies.
  • Ability to print silently (without showing dialogs) for automation scenarios.
  • Compatibility with .NET Framework, .NET Core, and .NET 7/8/9+ applications.

Why Microsoft Print Is Not Enough?
C# developers sometimes try to use Microsoft’s built-in printing APIs ( System.Drawing.Printing or PrintDocument ) to print PDFs. While these APIs work for text and graphics, they have significant limitations when it comes to direct PDF printing:

  • No native PDF support: The PrintDocument class cannot directly load and print PDFs. Developers often need extra workarounds, like rendering PDFs to images first.
  • External dependencies: You may need to install Adobe Reader or use Ghostscript to print PDFs, which introduces extra dependencies.
  • Limited control: Fine-grained features such as duplex printing, silent printing, or selecting custom paper sizes are difficult to implement.
  • Inconsistent results: Output may vary across different Windows environments, making it unreliable for enterprise use.

In short, while Microsoft’s print API works for simple scenarios, it doesn’t provide a professional, direct, and reliable solution for PDF printing. IronPrint is particularly useful for enterprise workflows where reports, invoices, or labels need to be printed automatically.

Step 1. Create a new Console application Project using Visual Studio
Create a new Visual Studio project.

Provide project path and name.

Select the required .NET version and create a project.


Step 2. Install IronPrint Nugget using Nugget package manager
Install the IronPrint nugget from the NuGet package manager console. A sample PDF file can be created using the IronPDF library.

dotnet add package IronPrint --version 2025.8.3

Step 3. Print PDF files using the IronPrint library
To print the required document, we can use the below simple code example.
using IronPrint;

// Set license key
License.LicenseKey = "your key";

// Print PDF directly
Printer.Print("sample.pdf");

// OR

// Show print dialog using GUI
Printer.ShowPrintDialog("sample.pdf");

Code Explanation

using IronPrint: Imports the IronPrint namespace.
License.LicenseKey = "your key": Activates IronPrint with your license key.
Printer.Print("sample.pdf"): Prints the given PDF file using the default printer and default settings.

Or Printer.ShowPrintDialog("sample.pdf"): Prints the given PDF file using the default printer and default settings and opens a dialog before printing.

Output

Step 4. Printer Settings
Printer Settings in IronPrint play a crucial role in the printing process, as they provide control over various aspects, including print quality, paper handling, cost efficiency, printer selection, resolution, consistency, automation, and industry-specific requirements, ultimately ensuring precise, reliable, and professional printing in C# applications. Users can set page range, print specific pages, printing mode etc.

using IronPrint;

License.LicenseKey = "my Key";

// Configure print settings with advanced printing features
PrintSettings printSettings = new PrintSettings();
printSettings.Dpi = 150;                       // Set printer resolution
printSettings.NumberOfCopies = 2;
printSettings.PaperOrientation = PaperOrientation.Portrait;
printSettings.PrinterName = "My Printer Network Name"; // Specify printer name

// Print the PDF document directly
Printer.Print("sample.pdf", printSettings);

Code Explanation

  • Using IronPrint: Imports the IronPrint namespace.
  • License.LicenseKey = "my Key": Activates IronPrint with your license key.
  • PrintSettings printSettings = new PrintSettings(): Creates a new object to define custom print options.
  • printSettings.Dpi = 150: Sets the print resolution to 150 DPI.
  • printSettings.NumberOfCopies = 2: Prints 2 copies of the document.
  • printSettings.PaperOrientation = PaperOrientation.Portrait: Prints pages in portrait orientation.
  • printSettings.PrinterName = "My Printer Network Name": Selects the specific printer by its network or system name.
  • Printer.Print("sample.pdf", printSettings): print method prints the sample.pdf file using the defined custom settings.

Output

IronPrint Licensing (Trial Available)
IronPrint requires a License to print documents and use all features. Developers can avail a trial license from here. Once you provide the email ID, the key will be delivered to you via email.

To use the key, just initialize it as shown below before the first use of the library.
License.LicenseKey = "my Key";

Real-World Applications of IronPrint

IronPrint is used across industries to automate and streamline printing tasks in .NET applications. Its flexibility and silent printing capabilities make it ideal for both desktop and server-side environments.

1. Invoice and Receipt Printing

Businesses use IronPrint to print invoices, receipts, and order confirmations automatically.

  • E-commerce platforms generate and print receipts after transactions.
  • Accounting systems print monthly invoices in batch mode.
  • POS systems use IronPrint for real-time receipt generation.

2. Shipping Labels and Logistics
IronPrint is widely used in logistics and warehouse management.

  • Print shipping labels with barcodes and QR codes.
  • Generate packing slips and delivery notes.
  • Integrate with IronBarcode and IronPDF for end-to-end document creation and printing.

3. Healthcare and Medical Records
Hospitals and clinics use IronPrint for.

  • Printing patient records, prescriptions, and lab reports.
  • Silent printing of appointment summaries and billing documents.
  • Integration with EMR systems for secure document handling.

4. Education and Certification
Educational institutions rely on IronPrint to.

  • Print student transcripts, certificates, and ID cards.
  • Automate printing of exam results and attendance sheets.
  • Support cross-platform printing for desktop and mobile apps.

5. Government and Legal Systems
Government agencies and legal firms use IronPrint for.

  • Printing legal documents, affidavits, and case files.
  • Batch printing of forms and notices.
  • Secure and silent printing in restricted environments.

6. Image and QR Code Printing
Retail and marketing teams use IronPrint to.

  • Print promotional materials, posters, and product tags.
  • Generate and print QR codes for campaigns.
  • Combine IronQR and IronPDF for pixel-perfect output

Conclusion
C# Print PDF feature is quite simple with IronPrint. Unlike Microsoft’s built-in print APIs, which lack native PDF compatibility and require other dependencies, IronPrint provides a straightforward, dependable, and professional-grade alternative. For printing PDFs in C#, IronPrint is a reliable and developer-friendly option. IronPrint simplifies the process and offers you total control over print tasks, whether you're developing a desktop application or a backend service. You can automate printing processes and provide users or hardware with high-quality output with just a few lines of code. Advanced printing features like duplex support, multiple copies, and quiet printing can be implemented with a few lines of code. IronPrint is a useful solution for any business-critical application that requires automated PDF printing.



European ASP.NET Core 9.0 Hosting - HostForLIFE :: Using ASP.NET Core to swiftly create minimal APIs

clock August 19, 2025 12:08 by author Peter

It is impossible to overestimate the significance of creating lightweight and effective APIs in the current web development environment. By reducing superfluous code and increasing developer productivity, minimal APIs offer an effective method of creating complicated APIs. Microsoft's open-source framework for web apps and services, ASP.NET Core, provides a foundation for creating simple APIs. This comprehensive tutorial will explore how to use ASP.NET Core to develop APIs, including key ideas, industry best practices, and practical examples.

Grasping the Concept of Minimal APIs in ASP.NET Core
Introduced in ASP.NET Core 6, minimal APIs present a method of constructing APIs without the traditional reliance on controllers and routing setup. Developers can now define endpoints using straightforward C# code that taps into the language's versatility and clarity. This streamlined approach minimizes the setup complexity involved in configuring APIs, making it particularly suitable for small-scale projects, prototypes, or microservices without worrying much about the development infrastructure to host and run APIs.

Key Characteristics of Minimal APIs
1. Simplified Syntax

Minimal APIs are known for their way of defining endpoints using C# code, with lambda expressions or methods instead of traditional controllers and routing setups. This approach cuts down on code, making API implementations cleaner and more concise.

2. Built-In Dependency Injection

ASP.NET Cores minimal APIs make use of the framework's built-in dependency injection container, enabling developers to inject dependencies into endpoint handlers. This promotes separation of concerns, enhances code reusability, and allows for the injection of dependencies like database contexts, services, or repositories without manual setup. This also helps drastically when writing unit tests.

3. Integration With ASP.NET Core Middleware

Minimal APIs seamlessly work with ASP.NET Core middleware, giving developers access to features like authentication, authorization, logging of requests/responses, and handling exceptions. By incorporating middleware components into the application pipeline without compromising simplicity, developers can enhance functionality while maintaining a development experience.

4. Support for OpenAPI/Swagger

ASP.NET Core Minimal APIs offer built-in support for Swagger integration, which helps in simplifying the process of generating API documentation. When developers add the Swashbuckle. ASP.NET Core package to the project and add a few lines of code to Program.cs, Swagger endpoints get created, which can automatically create API documentation that explains request/response structures, parameters, types, and error messages. This makes it easier to document and explain the API details to end users.

Exploring the Basics of Minimal APIs in ASP.NET Core 

Now that we've delved into the concept of APIs, in ASP.NET Core, let's dive into how to kickstart the process:

Step 1. Creating a New ASP.NET Core Project From CLIB

You can open a new minimal API solution using Visual Studio or using the .NET CLI. Let's use CLI to create an empty minimal API solution by running the command below. Now open it using Visual Studio by navigating to the folder where the MinimalApiDemo solution was created. Click on the MinimalApiDemo.csproj file to open the solution
dotnet new web -n MinimalApiDemo

Step 2. Defining Minimal API Endpoints

Define minimal API endpoints within the Program.cs file using the WebApplication class. 
var builder = WebApplication.CreateBuilder(args);

var app = builder.Build();

app.MapGet("/", () => "Hello World!");
app.MapGet("/greeting", () => "Welcome to my article about Minimal API!");

app.Run();


By default, you will get the Hello World endpoint out of the box, let's add another endpoint as shown in the above code snippet. We created an API endpoint that produces a greeting message by writing a single line. Creating API services can't get any simpler than this.

Step 3. Launching the Application
Use CLI to run the application or directly press F5 from Visual Studio. 
dotnet run

Visit http://localhost:5000/greeting in your web browser to view the response from the API endpoint to see the output, or Visual Studio will automatically open the browser as shown in the below figure.

Step 4. Adding Swagger Endpoints
To add Swagger to your project, you need to first install the below package directly from your Visual Studio package manager console.
dotnet add package Swashbuckle.AspNetCore

Modify your Program.cs to add the swaggerGenerator method and define the Swagger UI endpoint as shown below. 
var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddEndpointsApiExplorer(); // This is required for Swagger
builder.Services.AddSwaggerGen(); // This adds Swagger Generator

var app = builder.Build();

// Enable middleware to serve generated Swagger as a JSON endpoint.
app.UseSwagger();

// Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.),
// specifying the Swagger JSON endpoint.
app.UseSwaggerUI(c =>
{
    c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
});

app.MapGet("/", () => "Hello World!");

app.MapGet("/greeting", () => "Welcome to my article about Minimal API!");

app.Run();


When you run the application, you can now go to the Swagger endpoint by adding /swagger to the URL, which will open below the Swagger UI with details about your endpoints. 

Best Practices for Developing Minimal APIs in ASP.NET Core
To ensure fast sailing with your API development endeavors, it's crucial to adhere to these best practices.

1. Simplify and Focus on Endpoints
Make sure to create specific and straightforward endpoints for each task. Avoid creating complex endpoints that try to do too many things. Keeping your endpoints simple and focused makes your code easier to understand and debug.

2. Harness Dependency Injection
Use ASP.NET Core’s built-in tool for dependency injection to add dependencies to endpoint handlers. It’s crucial not to tie your endpoint logic with dependencies; instead, inject them as services. This approach enhances code reusability, testability, and maintainability by allowing for a separation of concerns.

3. Manage Errors Effectively
Ensure that your code includes error-handling mechanisms to manage exceptions and unforeseen issues in a manner. Utilize HTTP status codes and clear error messages to effectively communicate any errors to users. Be cautious not to reveal data, in error responses, and offer instructions on how users can address the problem.

4. Incorporate Validation and Input Sanitization Procedures

Make sure to check and clean up the input data to avoid security risks, like SQL injection or cross-site scripting (XSS) attacks. Employ data annotations, model validation attributes, or customized validation methods to maintain data security and integrity. Discard any incorrect input. Offer helpful error messages to users when needed.

5. Embrace Versioning and Documentation Practices

Utilize version control and documentation methods to guarantee operation and simplify connections with customer programs. Employ OpenAPI/Swagger for the creation of API documentation. Offer thorough explanations of endpoints, parameters, and response structures. Maintain versions of your APIs to ensure support for iterations and offer explicit instructions on transitioning clients to updated versions.

By adhering to these recommendations, you can construct APIs in ASP.NET Core that are effective, adaptable, and easy to manage. Ensure that your endpoints are straightforward and make use of dependency injection, manage errors with care, incorporate validation, input cleaning procedures, and offer documentation. By adopting these recommended approaches, you can develop APIs that cater to user requirements and facilitate integration with client applications.

Practical Instances of Minimal APIs in ASP.NET Core
Let's delve into some real scenarios demonstrating the power of creating minimal APIs in ASP.NET Core. Imagine you have an e-commerce application with product information inside a database. You want to spin up APIs to perform basic functionalities like create/read/update/delete products from the DB.

Let's write Minimal APIs for performing CRUD operations on the product class. I am using an in-memory database for simplicity.

Create a Product class and ProductContext a class inherited from DbContext (using Entity Framework to retrieve data from the DB).
public class ProductContext : DbContext
{
    public ProductContext(DbContextOptions<ProductContext> options)
        : base(options)
    {
    }

    public DbSet<Product> Products { get; set; }
}

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

Create/Read/Update/Delete API Endpoints inside a single file (program.cs) as shown below.
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.EntityFrameworkCore.InMemory;


var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<ProductContext>(options => options.UseInMemoryDatabase("Products"));

// Add services to the container.
builder.Services.AddEndpointsApiExplorer(); // This is required for Swagger
builder.Services.AddSwaggerGen(); // This adds Swagger Generator

var app = builder.Build();
// Enable middleware to serve generated Swagger as a JSON endpoint.
app.UseSwagger();

// Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.),
// specifying the Swagger JSON endpoint.
app.UseSwaggerUI(c =>
{
    c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
});


app.MapGet("/products", async (ProductContext db) =>
{
    return await db.Products.ToListAsync();
});

app.MapGet("/products/{id}", async (ProductContext db, int id) =>
{
    return await db.Products.FindAsync(id) is Product product ? Results.Ok(product) : Results.NotFound();
});

app.MapPost("/products", async (ProductContext db, Product product) =>
{
    db.Products.Add(product);
    await db.SaveChangesAsync();

    return Results.Created($"/products/{product.Id}", product);
});

app.MapPut("/products/{id}", async (ProductContext db, int id, Product inputProduct) =>
{
    if (await db.Products.FindAsync(id) is not Product product)
    {
        return Results.NotFound();
    }

    product.Name = inputProduct.Name;
    product.Price = inputProduct.Price;

    await db.SaveChangesAsync();

    return Results.NoContent();
});

app.MapDelete("/products/{id}", async (ProductContext db, int id) =>
{
    if (await db.Products.FindAsync(id) is not Product product)
    {
        return Results.NotFound();
    }

    db.Products.Remove(product);
    await db.SaveChangesAsync();

    return Results.NoContent();
});

app.Run();


We can spin up an API so fast by leveraging the power of Minimal APIs. Press F5 to open the browser. Navigate to Swagger UI by adding /swagger to the URL. Swagger UI will display all the endpoints as written in the above code block. 


How to Quickly Test It?
Click on any of the collapsible endpoints to see documentation. Click on a button to try it out and execute. I clicked on the HTTP post request to add a new Product called "Rocket Ship" to the in-memory database, which can then be retrieved by calling the GET Endpoint.


Conclusion
Using the ASP.NET Core framework to quickly design APIs offers a method for creating web APIs that are both efficient and lightweight. With the help of ASP.NET Core's built-in dependency injection, syntax, and smooth integration, developers can create APIs quickly and efficiently without the need for additional processes or complexity. Your API development journey will be successful if you follow suggested practices like keeping targeted endpoints, making good use of dependency injection, and handling mistakes with grace.



European ASP.NET Core 9.0 Hosting - HostForLIFE :: Limiting ASP.NET Login by IP Address

clock August 14, 2025 08:31 by author Peter

In many web applications, especially for sensitive areas like Admin Panels, we don’t want just anyone to access the login page. Even if they have valid credentials, restricting access by IP address adds an extra layer of security. In this post, I’ll show you how to allow login only from specific IP addresses using ASP.NET C# and web.config settings.

Why Restrict Access by IP?

  • Protects sensitive admin functionality from outside networks.
  • Limits exposure to brute-force or password-guessing attacks.
  • Helps in corporate environments where admins work from known locations.

Step 1. Store Allowed IP Addresses in web.config
Open your web.config file and add this under the <configuration> section:

<configuration>
  <appSettings>
    <!-- Comma-separated allowed IP addresses -->
    <add key="AllowedIPs" value="192.168.1.10,203.0.113.25,45.67.89.10" />
  </appSettings>
</configuration>


Notes

  • Multiple IPs are separated by commas.
  • You can add or remove IPs without touching the code — just update web.config.

Step 2. Check IP Address in Code-Behind

In your login.aspx.cs or any protected page’s code-behind:
using System;
using System.Configuration;
using System.Linq;
using System.Web.UI;

public partial class Admin_Login : System.Web.UI.Page
{
    protected void Go_Click(object sender, EventArgs e)
    {
        // Step 1: Get the client's IP address
        string ipaddress = Request.UserHostAddress.ToString();

        // Step 2: Get allowed IPs from web.config
        string allowedIPs = ConfigurationManager.AppSettings["AllowedIPs"];

        // Step 3: Convert string to array and trim spaces
        string[] ipList = allowedIPs.Split(',').Select(ip => ip.Trim()).ToArray();

        // Step 4: Check if IP is in the allowed list
        if (ipList.Contains(ipaddress))
        {
            // Allowed - Continue with login process
            Response.Redirect("dashboard.aspx");
        }
        else
        {
            // Not allowed - Show alert and stop
            string script = "alert('Access Denied! Your IP is not authorized to access this page.');";
            ScriptManager.RegisterStartupScript(this.Page, this.GetType(), "alertScript", script, true);
        }
    }
}


How It Works?

  • Request.UserHostAddress retrieves the IP address of the user trying to log in.
  • The code reads the list of allowed IPs from web.config.
  • It splits the list into an array and trims any spaces.
  • If the user’s IP matches any of the allowed IPs → login proceeds.
  • If not → a JavaScript alert displays "Access Denied!" and stops the process.

Important Tips

  • When testing locally, you might see 127.0.0.1 (IPv4) or ::1 (IPv6 loopback address).
  • That’s normal for localhost — to test real IP restrictions, deploy to a server, or access from another device.
  • For cloud hosting (Azure, AWS, etc.), sometimes you’ll need to check headers, like "HTTP_X_FORWARDED_FOR" for the real client IP.
  • Keep the web.config secure, never expose it publicly.

Conclusion
Restricting access by IP address is a simple yet effective security enhancement for admin login pages in ASP.NET. By keeping the allowed IP list in web.config, you can manage access without redeploying your application.



European ASP.NET Core 9.0 Hosting - HostForLIFE :: The Best Way to Simplify Your.NET Project

clock August 11, 2025 08:04 by author Peter

This post will show you the best practices for cleaning up your.NET project. Please read my previous post on best practices for cleaning up your.NET Core project before we begin.

Let's get started. The clean project principles are mostly the same, but in .NET Framework there are some differences in structure, DI, and configuration because:

  • There's no Program.cs with minimal hosting model.
  • You often work with ASP.NET MVC 5, Web API 2, or WCF instead of ASP.NET Core.
  • Dependency Injection and configuration are not built-in — you use NuGet packages (e.g., Autofac, Unity, Ninject).

Here’s the .NET Framework–specific best practices:

1. Keep a Layered Architecture

Example for ASP.NET MVC 5 / Web API 2:

MyApp.sln
 â”œâ”€ MyApp.Web         // MVC or Web API project (Controllers, Views)
 â”œâ”€ MyApp.Application // Service layer (business logic, DTOs)
 â”œâ”€ MyApp.Domain      // Entities, enums, interfaces
 â”œâ”€ MyApp.Infrastructure // EF6, repositories, external integrations
 â””─ MyApp.Tests       // Unit & integration tests


Note: You can still do feature-based folders inside Web or Application.

2. Use Dependency Injection (Manually Registered)

In .NET Framework, you add a DI container manually, for example Autofac:
var builder = new ContainerBuilder();
builder.RegisterControllers(typeof(MvcApplication).Assembly);
builder.RegisterType<OrderService>().As<IOrderService>();
builder.RegisterType<OrderRepository>().As<IOrderRepository>();

var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));


Note: Do this in Global.asax → Application_Start().

3. Keep Controllers Thin

Same as in Core: controllers only handle HTTP flow — move logic into services.

4. Use ViewModels & DTOs

Avoid passing EF entities directly to views or API responses.
Use AutoMapper for mapping between domain models and DTOs:
Mapper.Initialize(cfg => cfg.CreateMap<Order, OrderDto>());

5. Centralize Exception Handling
In MVC/Web API, use:
Global Filters:
public class GlobalExceptionFilter : IExceptionFilter {
    public void OnException(ExceptionContext filterContext) {
        // log error
        filterContext.Result = new ViewResult { ViewName = "Error" };
        filterContext.ExceptionHandled = true;
    }
}


Register in FilterConfig.cs
6. Keep Configuration Out of Code
Use Web.config for settings.
For strongly typed configs:
var settingValue = ConfigurationManager.AppSettings["MySetting"];

Or use Settings.settings file for auto-generated config classes.

7. Avoid Magic Strings / Numbers
Same principle:
public static class Roles {
    public const string Admin = "Admin";
}

8. Apply SOLID
Even in .NET Framework — especially important because older projects tend to get “God classes”.

9. Use Filters & Action Attributes

Instead of putting auth/logging/validation code in controllers:

  • AuthorizationFilterAttribute for role-based checks.
  • ActionFilterAttribute for logging and pre/post action hooks.

10. Use EF6 Best Practices

  • Avoid lazy loading unless needed.
  • Use AsNoTracking() for queries that don’t need entity tracking.
  • Keep DB logic in repositories or a dedicated DAL.

11. Unit Testing Without Core’s Built-in DI
Mock services using Moq/FakeItEasy.
Avoid static dependencies — make them injectable.

12. Keep Global.asax Clean

  • Move route configs to RouteConfig.cs.
  • Bundle/minify in BundleConfig.cs.
  • Register filters in FilterConfig.cs.
  • Only call setup methods in Application_Start().


13. Static Analysis & Style Rules
Use FxCop, StyleCop, or ReSharper for code quality.

14. Async in ASP.NET

Use async/await in MVC/Web API to free threads for scalability.

public async Task<ActionResult> GetOrders() {
    var orders = await _orderService.GetOrdersAsync();
    return Json(orders, JsonRequestBehavior.AllowGet);
}


15. Document Your APIs
For Web API 2, use Swashbuckle for .NET Framework to generate Swagger docs.

Conclusion
Here we tried to cover Best practice to make your project cleaner in .NET



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