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 Value | What Happens | Best 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
Setting | Why Required | Purpose |
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&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&subsection1=$2&pagename1=$3&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 .