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 :: ASP.NET Web.Config: Redirects, Security, and URL Rewriting Explained

clock October 2, 2025 07:20 by author Peter

In ASP.NET applications, the Web.config file is the heart of configuration. It allows us to define application settings, connection strings, error handling, session timeouts, security rules, and even URL rewriting without touching our C# backend code.

In this blog, we’ll explore:

  • The concept of Web.config
  • Redirect usage through Web.config
  • Page protection and security settings
  • URL rewriting for clean SEO-friendly URLs
  • Frontend usages (single name, double name, third parameter, redirects)

And finally, we’ll go line by line through a real-world Web.config example.

What is Web.config?

  • A special XML file used in ASP.NET applications.
  • It defines configuration settings such as database connections, authentication, authorization, custom errors, and security headers.
  • Stored at the root of the application.

What is <customErrors> in ASP.NET?

  • <customErrors> is a configuration element in Web.config that controls how errors are handled and displayed in ASP.NET applications.
  • Instead of showing raw ASP.NET/YELLOW ERROR PAGES (with stack trace), we can show friendly error pages (like Errorpage.aspx ).
  • This improves user experience and also protects sensitive error details from hackers.

1. Three Ways (Modes) of Using <customErrors>
customErrors with Mode="Off" and Status Codes Defined

<customErrors mode="Off">
  <error statusCode="400" redirect="Errorpage.aspx" />
  <error statusCode="403" redirect="Errorpage.aspx" />
  <error statusCode="404" redirect="Errorpage.aspx" />
  <error statusCode="500" redirect="Errorpage.aspx" />
</customErrors>


Explanation

  • mode="Off" → Application will display detailed ASP.NET error pages (stack trace, line numbers).
  • But here, specific error code redirections are defined.
  • If you visit a page that doesn’t exist → it redirects to Errorpage.aspx .
  • This is generally useful in development environments, where you need to debug errors but also want some controlled redirections.
  • If a 404 Not Found error occurs → User is redirected to Errorpage.aspx .
  • If a 500 Internal Server Error occurs → Same redirection.

Purpose: Developer debugging + handling user-friendly redirects.

2. customErrors with Mode="Off" (Single Line)
<customErrors mode="Off"/>

Explanation

  • Application will always show detailed error messages .
  • No redirection is done.
  • Useful only in local development/testing — never recommended for production.

Purpose: Debugging only (not secure).

3. customErrors with Mode="On"
<customErrors mode="On"/>

Explanation

  • Application will hide detailed error messages.
  • Instead, it will show friendly custom error pages (like Errorpage.aspx).
  • Secure approach for production environments.

Purpose: Protect sensitive error details from users/hackers, show professional error pages.

 

Quick Comparison

Mode ValueWhat HappensBest Used In
Off (with mapping) Shows detailed ASP.NET errors but allows redirection for specific status codes Development/Debugging
Off (without mapping) Shows raw errors always Local debugging only
On Shows user-friendly custom error pages (e.g., Errorpage.aspx) Production (secure)

Final Takeaway:

 

  • Mode=Off → Developer Mode (debugging)
  • Mode=On → Production Mode (secure, user-friendly)
  • Mode=Off with status codes → Debugging + Controlled Redirection

Securing Pages with Web.config
Code Section

<validation validateIntegratedModeConfiguration="false"/>
<httpProtocol>
  <customHeaders>
    <remove name="X-AspNet-Version"/>
    <remove name="X-AspNetMvc-Version"/>
    <remove name="X-Powered-By"/>
    <add name="Body-Count" value="Ice-T"/>
    <add name="Access-Control-Allow-Credentials" value="true"/>
    <add name="Access-Control-Allow-Headers" value="content-type"/>
    <add name="X-Content-Type-Options" value="nosniff"/>
    <add name="X-XSS-Protection" value="1; mode=block"/>
    <add name="Cache-Control" value="no-cache, no-store, must-revalidate"/>
    <add name="X-Frame-Options" value="SAMEORIGIN"/>
    <add name="X-Permitted-Cross-Domain-Policies" value="none"/>
    <add name="Strict-Transport-Security" value="max-age=31536000; includeSubDomains"/>
    <add name="Permissions-Policy" value="accelerometer=(), camera=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), payment=(), usb=()"/>
  </customHeaders>
</httpProtocol>

Line-by-Line Explanation
1. Validation Mode

<validation validateIntegratedModeConfiguration="false"/>

  • Concept: Controls validation of the IIS Integrated Pipeline configuration.
  • Why Required: Sometimes, older Web.config settings are not compatible with IIS 7+ Integrated Pipeline mode.
  • Purpose: Setting false tells ASP.NET not to validate older settings → prevents unnecessary runtime errors.

2. Removing Headers (Information Disclosure Prevention)
<remove name="X-AspNet-Version"/>
<remove name="X-AspNetMvc-Version"/>
<remove name="X-Powered-By"/>

  • Concept: By default, ASP.NET/IIS sends these headers in HTTP responses.
  • Why required: Hackers can identify framework versions and target known vulnerabilities.
  • Purpose: Security through obfuscation → don’t expose technology stack details.

3. Adding Custom Headers
a) Fake Header (Obfuscation / Branding)
<add name="Body-Count" value="Ice-T"/>

  • Concept: Adds a custom header with an arbitrary value.
  • Why Required: Not mandatory, but can be used for tracking or branding.
  • Purpose: Demonstration/fun — here it’s "Ice-T" (artist’s name), doesn’t affect functionality.

b) CORS Headers (Cross-Origin Resource Sharing)
<add name="Access-Control-Allow-Credentials" value="true"/>
<add name="Access-Control-Allow-Headers" value="content-type"/>


Concept: Defines rules for cross-origin requests.
Why required: If your API is called from JavaScript on another domain.


Purpose

  • Allow-Credentials=true → lets cookies/auth headers be sent in cross-domain requests.
  • Allow-Headers=content-type → allows Content-Type header in requests.

c) Content Security Headers
<add name="X-Content-Type-Options" value="nosniff"/>

  • Concept : Stops browsers from MIME-type sniffing.
  • Why Required: Prevents malicious file uploads from being misinterpreted (e.g., .jpg running as script).
  • Purpose: Protects against content-type-based attacks.

d) XSS Protection
<add name="X-XSS-Protection" value="1; mode=block"/>
Concept: Activates the browser’s built-in XSS (Cross-Site Scripting) filter.

  • Why Required: Prevents malicious scripts from executing in the browser.
  • Purpose: Block pages if XSS is detected.

e) Cache Control
<add name="Cache-Control" value="no-cache, no-store, must-revalidate"/>

  • Concept : Prevents caching of sensitive content.
  • Why Required : Avoids storing confidential pages in browser/proxy cache.
  • Purpose : Ensures always fresh content, good for banking/financial apps.

f) Clickjacking Protection
<add name="X-Frame-Options" value="SAMEORIGIN"/>

  • Concept: Controls iframe embedding.
  • Why Required: Attackers can load your site inside a hidden iframe and trick users (clickjacking).
  • Purpose: Allows embedding only from the same domain.

g) Cross-Domain Policy
<add name="X-Permitted-Cross-Domain-Policies" value="none"/>

  • Concept: Restricts Adobe Flash, PDF, or other plugins from making cross-domain requests.
  • Why Required: Stops unauthorized access from plugins.
  • Purpose: Set to none for strictest security.

h) Strict Transport Security (HSTS)
<add name="Strict-Transport-Security" value="max-age=31536000; includeSubDomains"/>

  • Concept: Forces browser to use HTTPS for all requests.
  • Why Required: Prevents downgrade attacks and cookie hijacking on HTTP.
  • Purpose: Enforces HTTPS for 1 year ( 31536000 seconds ).

i) Permissions Policy (Feature Control)
<add name="Permissions-Policy" value="accelerometer=(), camera=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), payment=(), usb=()"/>

  • Concept: Controls access to powerful browser APIs.
  • Why Required: Protects privacy by blocking unnecessary device features.
  • Purpose: Disables camera, microphone, location, USB, etc., unless explicitly allowed.

Summary Table

SettingWhy RequiredPurpose
validateIntegratedModeConfiguration Avoids IIS config errors Compatibility
Remove X-* headers Prevents info leakage Security
Access-Control-* Allow safe CORS Cross-domain support
X-Content-Type-Options Stop MIME sniffing Content security
X-XSS-Protection Prevent script injection XSS defense
Cache-Control Avoid sensitive data caching Privacy & security
X-Frame-Options Prevent clickjacking UI protection
X-Permitted-Cross-Domain-Policies Restrict plugins Security
Strict-Transport-Security Force HTTPS Encryption
Permissions-Policy Limit device APIs Privacy & control

URL Rewriting in Web.config

Instead of exposing raw .aspx paths, you can provide clean SEO-friendly URLs .

Your rewriter section:

<rewriter>
  <rewrite url="/about-us" to="About.aspx" processing="stop"/>
  <rewrite url="/contact-us" to="/contact_us.aspx" processing="stop"/>
  <rewrite url="/faq" to="faq.aspx" processing="stop"/>
</rewriter>

XML

Usage in frontend:

<ul>
  <li><a href="/faq">FAQ's</a></li>
  <li><a href="/about-us">About Us</a></li>
  <li><a href="/contact-us">Contact Us</a></li>
</ul>

HTML

Even though the user clicks /about-us , it internally loads About.aspx .
Frontend Rewrite Examples
Single Name Rewrite

<rewrite url="/faq" to="faq.aspx" processing="stop"/>

XML

Usage

<a href="/faq">FAQ's</a>

HTML
Double Name Rewrite

<rewrite url="/productlistpage/([^/]+)?$" to="/productlistpage/products.aspx?opt=$1" processing="stop"/>

XML

Usage

<a href="/productlistpage/equity">Equity</a>
<a href="/productlistpage/mutual-fund">Mutual Funds</a>

HTML
Third Parameter Passed

<rewrite url="/productlistpage/([^/]+)/([^/]+)?$" to="/productlistpage/frequency.aspx?opt=$1&amp;freq=$2" processing="stop"/>

XML

Usage

<a href="/productlistpage/delayed/3">Delayed</a>
<a href="/productlistpage/historical/2">Historical</a>
<a href="/productlistpage/eod/1">End of the Day</a>

HTML
Redirect with Multiple Parameters

<rewrite url="/productlistpage/([^/]+)/([^/]+)/([^/]+)/([^/]+)?$"
     to="/indexlist.aspx?section1=$1&amp;subsection1=$2&amp;pagename1=$3&amp;srno1=$4" processing="stop"/>

XML

This allows structured redirection for advanced product details.
<appSettings> Section Examples

The <appSettings> block in Web.config (or App.config) is used to store key–value pairs for application-wide settings.
It makes configuration easier to manage without hardcoding values in your C# code.

Example Breakdown

<appSettings>
    <add key="MailServer" value="1443.708.661.165" />
    <add key="Liveurl" value="https://www.blackbox.ai/chat/aXzGGY0"/>
    <add key="emailWhitelist" value="[email protected]"/>
    <add key="updatehours" value="4"/>
    <add key="AllowedIPs" value="122.168.1.003,122.168.1.888"/>
</appSettings>

Explanation
MailServer → Stores your mail server IP (instead of hardcoding SMTP IP in code).
    Purpose: Used by your app to send emails.

Liveurl → Stores an external service URL.
    Purpose: Centralized URL for API calls or redirections.

emailWhitelist → List of allowed emails.
    Purpose: Security check – only these emails can access/send certain features.

updatehours → Numeric setting (like refresh/update interval)
    Purpose: Defines how often the app should refresh data (in hours).

AllowedIPs → List of IPs that can access the application.
    Purpose: Security filtering based on client IP addresses.

Instead of hardcoding, your C# code retrieves values using:
  string mailServer = ConfigurationManager.AppSettings["MailServer"];


<connectionStrings> Section

The <connectionStrings> block is used to define database connection details.
This helps in connecting your .NET application to SQL Server (or other DBs) without storing credentials in code.

Example Breakdown

<connectionStrings>
    <add name="DBName1" connectionString="Data Source=softsql;Initial Catalog=indiasector;Connect TimeOut=60; Max Pool Size=10000;user id=sa;password=capmark@09" providerName="System.Data.SqlClient"/>
    <add name="DBName2" connectionString="Data Source=softsql;Initial Catalog=CommonDB;Connect TimeOut=60; Max Pool Size=10000;user id=sa;password=capmark@09" providerName="System.Data.SqlClient"/>
    <add name="DBName3" connectionString="Data Source=softsql;Initial Catalog=CmotsAPI;Connect TimeOut=60; Max Pool Size=10000 ;User ID=sa;Password=capmark@09" providerName="System.Data.SqlClient"/>
</connectionStrings>


Explanation
  • name="DBName1" → Identifier used in code.
  • string conn = ConfigurationManager.ConnectionStrings["DBName1"].ConnectionString;
  • Data Source=softsql → SQL Server name or IP.
  • Initial Catalog=indiasector → Database name to connect.
  • Connect Timeout=60 → Timeout in seconds if connection fails.
  • Max Pool Size=10000 → Max concurrent connections allowed in pool.
  • user id / password → Database login credentials.
  • providerName=" System.Data .SqlClient" → Provider type (here it’s SQL Server).
Each <add> here represents one DB connection.
Your application may connect to multiple databases ( indiasector , CommonDB , CmotsAPI ) depending on modules.
<system.web>

<system.web>
    <sessionState timeout="60"></sessionState>
</system.web>


Explanation
<sessionState timeout="60">

Purpose: Controls how long a user’s session remains active (in minutes).
timeout="60" → The session will expire after 60 minutes of inactivity.

Example: If a user logs in and then doesn’t perform any action for 1 hour, their session automatically ends and they may be logged out.
<system.web><rewrite> ... </rewrite></system.web>

<system.web>
  <rewrite>
      <outboundRules>
        <rule name="Remove RESPONSE_Server">
          <match serverVariable="RESPONSE_Server" pattern=".+"/>
          <action type="Rewrite" value=""/>
        </rule>
        <rule name="Remove X-Powered-By">
          <match serverVariable="RESPONSE_X-Powered-By" pattern=".+"/>
          <action type="Rewrite" value="pagename"/>
        </rule>
      </outboundRules>
  </rewrite>

  <security>
      <requestFiltering>
        <requestLimits maxAllowedContentLength="2147483647"/>
      </requestFiltering>
  </security>
</system.web>

Explanation
<rewrite>

This section belongs to IIS URL Rewrite Module.

It allows you to manipulate incoming requests and outgoing responses .

Here you are using outbound rules → which modify the HTTP response headers before they are sent to the client.

1. <rule name="Remove RESPONSE_Server">
Purpose: Removes the Server header from the HTTP response.
<match serverVariable="RESPONSE_Server" pattern=".+"/> → Matches any value of the Server header.
<action type="Rewrite" value=""/> → Rewrites it with an empty value (effectively removing it).


Benefit: Hides server technology (IIS, Apache, etc.) → improves security by preventing attackers from knowing which server you are using.

2. <rule name="Remove X-Powered-By">
Purpose: Modifies the X-Powered-By header in the HTTP response.
<match serverVariable="RESPONSE_X-Powered-By" pattern=".+"/> → Matches any existing value of the X-Powered-By header.
<action type="Rewrite" value="ABCIPO"/> → Replaces it with a custom value "ABCIPO" .


Benefit: Instead of exposing .NET / IIS version , you can mask it with your own text for security through obfuscation.
<security>


The security section applies additional security configurations to requests.

3. <requestFiltering>
Purpose: Defines restrictions on requests to protect your application from malicious uploads or attacks.
<requestLimits maxAllowedContentLength="2147483647"/>

Sets the maximum allowed request size.

Value 2147483647 = 2 GB (maximum limit for IIS in bytes).

This allows very large file uploads (like videos, ZIPs, datasets).

Be careful → very large uploads can impact server performance or be abused for DoS attacks .


European ASP.NET Core 9.0 Hosting - HostForLIFE :: Plan for Responding to Security Vulnerabilities in ASP.NET Core Applications

clock September 23, 2025 08:49 by author Peter

No application is completely impervious to security risks. Even with the finest safe coding techniques, vulnerabilities, configuration errors, and third-party dependencies can still be exploited by attackers. To promptly identify, address, and recover from security breaches, each ASP.NET Core application needs a clear Incident Response Plan (IRP).


The procedures, resources, and sample code for creating an incident response plan designed especially for ASP.NET Core applications are all covered in this article.

What Is an Incident Response Plan?
An Incident Response Plan (IRP) is a documented, structured approach to handling security breaches. Its purpose is to:

  • Detect suspicious or malicious activity quickly.
  • Contain and mitigate damage.
  • Eradicate the root cause of the breach.
  • Recover normal operations.
  • Learn from incidents to prevent future breaches.
  • Key Phases of Incident Response in ASP.NET Core

1. Preparation
Before a breach happens, ensure:

  • Security logging and monitoring are enabled.
  • Alerts are configured for unusual activities (e.g., failed logins, suspicious API calls).
  • Teams know their roles and escalation paths.
  • Backups and recovery procedures are in place.

Example: Enable structured security logging with Serilog or Application Insights:
Log.Logger = new LoggerConfiguration()
    .Enrich.FromLogContext()
    .WriteTo.Console()
    .WriteTo.File("logs/security-.log", rollingInterval: RollingInterval.Day)
    .CreateLogger();


2. Identification
Detect and confirm the breach.
Common signs in ASP.NET Core apps include:

  • Multiple failed login attempts (brute force).
  • Unauthorized access to protected endpoints.
  • Sudden spikes in API traffic (possible DoS).
  • Unexpected changes in configuration or database.

Example: Log and flag repeated failed logins:
_logger.LogWarning("Failed login attempt {Count} for {Username} from {IP}",
                   attemptCount, username, ip);
if (attemptCount > 5)
{
    _logger.LogError("Possible brute-force attack detected from IP {IP}", ip);
    // Trigger an alert or block IP temporarily
}

3. Containment
Limit the scope of the breach while keeping services running.
Disable compromised accounts.

Block malicious IPs temporarily.

Isolate affected microservices or APIs.

Example: Blocking an IP using ASP.NET Core middleware:
public class IpBlockMiddleware
{
    private readonly RequestDelegate _next;
    private static readonly HashSet<string> BlockedIps = new();

    public IpBlockMiddleware(RequestDelegate next) => _next = next;

    public async Task Invoke(HttpContext context)
    {
        var ip = context.Connection.RemoteIpAddress?.ToString();
        if (BlockedIps.Contains(ip))
        {
            context.Response.StatusCode = 403;
            await context.Response.WriteAsync("Access denied.");
            return;
        }

        await _next(context);
    }

    public static void BlockIp(string ip) => BlockedIps.Add(ip);
}


4. Eradication
Remove the root cause of the breach.

  • Patch vulnerable dependencies (e.g., NuGet packages).
  • Fix misconfigured CORS, authentication, or authorization policies.
  • Remove injected malicious code or unauthorized files.

Use OWASP Dependency Check or dotnet list package --outdated to identify vulnerabilities.

5. Recovery

Restore services to normal operations.

  • Rotate compromised keys, tokens, or certificates.
  • Restore data from clean backups if tampered with.
  • Gradually reintroduce blocked IPs/users after ensuring safety.
  • Monitor closely for recurrence.

6. Lessons Learned
After the incident, perform a post-mortem analysis:

  • What was the root cause?
  • How was it detected?
  • Were response times acceptable?
  • What controls can prevent recurrence?

Document findings and improve the incident response playbook.

Automating Incident Response in ASP.NET Core
You can integrate automated workflows for faster response:

  • Azure Sentinel or AWS GuardDuty—Automatically trigger alerts and block malicious IPs.
  • Webhook-based alerts – Notify your team on Slack/Teams when security anomalies occur.
  • Custom ASP.NET Core filters—Enforce consistent logging and security checks across controllers.

Example: Global exception logging with IExceptionFilter:
public class SecurityExceptionFilter : IExceptionFilter
{
    private readonly ILogger<SecurityExceptionFilter> _logger;

    public SecurityExceptionFilter(ILogger<SecurityExceptionFilter> logger)
    {
        _logger = logger;
    }

    public void OnException(ExceptionContext context)
    {
        _logger.LogError(context.Exception,
                         "Security exception at {Path}",
                         context.HttpContext.Request.Path);
    }
}


Incident Response Checklist for ASP.NET Core Apps

  • Enable detailed, structured security logging.
  • Monitor logs using SIEM tools (Azure Sentinel, ELK, Splunk).
  • Configure alerts for brute-force and suspicious activity.
  • Implement containment mechanisms (IP blocking, account disabling).
  • Regularly patch dependencies and frameworks.
  • Practice recovery via backups and incident simulations.
  • Conduct post-incident reviews and update your IRP.

Conclusion
A well-prepared incident response plan ensures that your ASP.NET Core applications can withstand breaches and recover with minimal damage. By combining proactive monitoring, structured logging, automated containment, and post-incident learning, your development and security teams can respond to threats effectively.



European ASP.NET Core 9.0 Hosting - HostForLIFE :: How to Use ASP.NET Core Data Protection APIs?

clock September 18, 2025 08:19 by author Peter

The Data Protection API (DPAPI), which is included into ASP.NET Core, offers developers easy, safe, and expandable cryptographic operations. The framework itself makes extensive use of it internally, for instance, to safeguard OAuth state, CSRF tokens, and authentication cookies. This post describes how to use ASP.NET Core's Data Protection APIs to safeguard your private information.

The Data Protection API: What is it?
ASP.NET Core's Data Protection API is a cryptography framework made to:

  • Encrypt and decrypt data, such as tokens and connection strings.
  • Securely handle keys (with support for key rotation).
  • Assure confidentiality and resistance to tampering.
  • Connect with ASP.NET Core components with ease.

You depend on a managed service that takes care of algorithm selection, key management, and lifetime automatically rather than handling cryptography by yourself.

Setting Up Data Protection in ASP.NET Core
The Data Protection service is registered within Program.cs or Startup.cs.
var builder = WebApplication.CreateBuilder(args);

// Register Data Protection services
builder.Services.AddDataProtection();

builder.Services.AddControllers();
var app = builder.Build();
app.MapControllers();
app.Run();

This sets up the Data Protection system with in-memory key storage (by default).

Protecting and Unprotecting Data
Create a service that uses the IDataProtector interface:
using Microsoft.AspNetCore.DataProtection;

public class EncryptionService
{
    private readonly IDataProtector _protector;

    public EncryptionService(IDataProtectionProvider provider)
    {
        // Create a protector with a unique purpose string
        _protector = provider.CreateProtector("MyApp.DataProtection.Demo");
    }

    public string Protect(string plainText)
    {
        return _protector.Protect(plainText);
    }

    public string Unprotect(string protectedData)
    {
        return _protector.Unprotect(protectedData);
    }
}

Register it in Program.cs:
builder.Services.AddScoped<EncryptionService>();

Usage in a controller:
[ApiController]
[Route("api/[controller]")]
public class SecureController : ControllerBase
{
    private readonly EncryptionService _encryptionService;

    public SecureController(EncryptionService encryptionService)
    {
        _encryptionService = encryptionService;
    }

    [HttpGet("protect")]
    public string ProtectData(string input)
    {
        return _encryptionService.Protect(input);
    }

    [HttpGet("unprotect")]
    public string UnprotectData(string input)
    {
        return _encryptionService.Unprotect(input);
    }
}

Persisting Keys (Production Scenarios)
By default, keys are stored in-memory and lost when the app restarts. For production, configure persistent key storage.

File System Storage
builder.Services.AddDataProtection()
    .PersistKeysToFileSystem(new DirectoryInfo(@"C:\keys"))
    .SetApplicationName("MyApp");

Azure Blob Storage
builder.Services.AddDataProtection()
    .PersistKeysToAzureBlobStorage(
        new Uri("https://<account>.blob.core.windows.net/keys/key.xml"),
        new DefaultAzureCredential());


Redis (for multiple instances)
builder.Services.AddDataProtection()
    .PersistKeysToStackExchangeRedis(connectionMultiplexer, "DataProtection-Keys");


Key Management and Rotation

  • Keys are automatically rotated every 90 days (configurable).
  • Old keys are retained for decrypting data.
  • You can manually configure key lifetimes:

builder.Services.AddDataProtection()
    .SetDefaultKeyLifetime(TimeSpan.FromDays(30));


Common Use Cases

  • Protecting sensitive settings (e.g., API keys).
  • Encrypting tokens or IDs before sending them in URLs.
  • Securing cookies and session state (handled automatically).
  • Multi-instance apps (persist keys to shared storage).

Best Practices

  • Always persist keys in production.
  • Use a unique purpose string for each protected data type.
  • Store keys in secure locations (Azure Key Vault, Blob Storage, Redis).
  • Rotate keys regularly.
  • Never hardcode secrets—use environment variables or secret managers.

Conclusion
The ASP.NET Core Data Protection API provides a secure and developer-friendly way to handle encryption without needing deep cryptography knowledge. Whether you’re protecting sensitive values in configuration, encrypting tokens, or securing cookies, the Data Protection system ensures your app stays resilient against common cryptographic pitfalls. With persistent key storage, key rotation, and integration with cloud services, it’s ready for enterprise-grade applications.



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.



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