Publishing/deploying ASP.NET web sites is easier and more efficient with Microsoft’s deployment tool, called Web Deploy. I will be showing how to publish and deploy a web site step by step.
What you will use is:
Visual Studio (the tool in which you develop your web site)
Web Deploy (the tool that installs necessary components)
IIS (the tool that publishes your web site )
End-to-end steps:
In Visual Studio, Go to “Build > Publish projectname“. In the wizard, configure the settings:
Profile: Create a new profile if there is no one exits
Connection: Select “Web Deploy Package” in Publish Method list. Choose a path
Settings: Keep it as is
Preview: Click “Publish”. We will use the zip file in step 3
Click on the web site. Click the link “Import Application“
Specify the “zip” file you created in step 1
Importing the application in IIS
Yes, that’s all!
.
Note: If you get an error saying that some dll files are missing (example error message is below), find those files in the computer you use for developing and copy them under “C:\inetpub\wwwroot\websitename\applicationname\bin“.
Some DLL files are missing. You should copy them manually
You may run into this error message in your ASP.NET project:
System.Threading.ThreadAbortException: Thread was being aborted.
It means that executing some part of your code took time more than it is allowed. You can trace the stack to see which lines they are. If you trust your code, it is a good idea to increase timeout value so the thread won’t aborted again.
Resolution
Add this code or change it if it’s already exist in your web.config file:
You may come across this error when you run your ASP.NET application first time:
Description: The application attempted to perform an operation not allowed by the security policy. To grant this application the required permission please contact your system administrator or change the application’s trust level in the configuration file.
Exception Details: System.Security.SecurityException: Request for the permission of type ‘System.Security.Permissions.FileIOPermission, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089′ failed.
ASP.NET trust level error
Solution
All about permissions. You need to grant required permissions to your application. To do this, simply add the code below into your web.config file.
When you try to view your webpage, you may run into this error:
HTTP Error 404.15 – Not Found The request filtering module is configured to deny a request where the query string is too long.
Cause
This problem occurs if you:
Create a Web Application with .NET Framework 4.5.2 targeted AND
Host your application in IIS AND
Disable anonymous access
Following solution will help you to sort this problem out without changing your configuration.
Solution
In order to get rid of this infinite loop, you can enable anonymous access. However, you may not want to enable it because of some security or functionality reasons such as getting users’ logon name. The other solution is that:
I’ve recently spent some time to find a best way to get visitors’ Active Directory name in my ASP.NET page. You’ll find a list of techniques.
Note: Some of them may require cookies to be enabled or need Anonymous Access to be disabled in IIS. Also you may need to do string parsing in some cases.
You may get this error when you visit your ASP.NET webpage:
Parser Error Message: Failed to decrypt using provider ‘RsaProtected ConfigurationProvider’. Error message from the provider: The RSA key container could not be opened.
You have probably just ecrypted connection strings in web.config. This error states that IIS wasn’t able to decrypt your connectiion string.
Resolution
Check your authentication settings first (Windows, Forms, Anonymous, Impersonation etc). Make sure you enable the ones you need.
If this doesn’t solve the issue, it means that you didn’t grant access to your ASP.NET user on RSA container. Open command prompt and run this command:
Make sure you put the correct container name for “DemoWebsiteConfigurationKey” and default ASP.NET account instead of “NT Authority\Network Service”. To find out your container name, look for “keyContainerName” parameter in your web.config or machine.config (%windir%\Microsoft.NET\Framework\[version]\config\machine.config).
Found (302): Tells the web client to issue a new request to the location. Also called “Moved Temporarily”. This is the default option.
Permanent (301): Tells the web client that the location requested has permanently changed. If a client has link-editing capabilities, it should update all references to the Request URL. The response is cachable. If the 301 status code is received in response to a request of any type other than GET or HEAD, the client must ask the user before redirecting. Also called “Moved permanently”.
Temporary (307): The request should be repeated with another URL; however, future requests should still use the original URL. In contrast to 302 status code, the request method is not allowed to be changed when reissuing the original request. For instance, a POST request should be repeated using another POST request. Prevents a Web browser from losing data when the browser issues an HTTP POST request. Also called “Temporary Redirect”
If you are (still) developing with Classic ASP, you might have noticed how hard it is to debug your applications. Classic ASP has its own settings which are different than the ones .NET has.
A generic error page
.
These 3 steps will help you to detect errors in your application successfully.
1- Turn on IIS debugging for ASP
IIS doesn’t send debugging details to browser by default. You can change this behavior and ask IIS to send details such as line number and trace to user:
Open IIS Manager. Click the application name
Double click “ASP“
Expand “Debugging Properties“
For the attribute “Send Errors to Browser“, select “True“
IIS debugging settings for Classic ASP
.
2- Configure Error Pages
You can tell IIS to show details on common error pages such as 401, 404, 500:
Open IIS Manager. Click the application name
Double click “Error Pages“
Click on the error code
In Action Pane, click “Edit Feature Settings“
Select “Detailed errors“
Properties for common error pages
.
3- Let Internet Explorer to show error details
IE wants to show friendly error pages instead of detailed ones that are useful for developers. You can change this setting for debugging purposes:
Open Internet Explorer
Go to “Tools > Internet Options > Advanced“
Unselect “Show friendly HTTP error messages“
Internet Explorer settings
.
New error page will look like this:
Finally! We have a little bit more details about the error
The less you give to hackers, the safer your web application is. Hiding the product, technology, and version information of your server is one big step towards narrowing the attack surface of your application.
By default, IIS server will reveal this data to everyone who has access to your application:
Server: Microsoft-IIS/7.5
X-AspNet-Version: 2.0.50727
X-Powered-By: ASP.NET
This data can be viewed by a proxy such as Fiddler.
Server details
You can remove these headers by add a few lines into web.config and Global.asax files. You don’t need to do any configuration changes in IIS if you are using IIS 7 or an upper version. .
You may wonder what type of browsers your visitors have. The best way to collect this information is using an analytics service such as Google Analytics.
What if you don’t use any analytics service but still want to collect browser stats? Your only option is that digging into web server logs. However, it’s not easy because web server logs provide user-agent data. It doesn’t provide direct browser information.
Here is how IIS logs look like:
How to Get Browser Info from IIS Data?
Follow these steps to convert raw IIS log to meaningful browser stats:
Copy IIS logs to a folder (IIS logs are typically in C:\inetpub\logs\LogFiles)
You may come across this error message when you get around in pages of your ASP.NET website:
Validation of viewstate MAC failed. If this application is hosted by a Web Farm or cluster, ensure that <machineKey> configuration specifies the same validationKey and validation algorithm. AutoGenerate cannot be used in a cluster.
Background
ASP.NET uses view-state variable to rebuild pages after post-backs. The text of your buttons and the value of the form fields are the examples that this variable stores.
In order to prevent tempering attacks that try to play around with view-state data to force your webpage behave unexpectedly, web server validates the view-state data between page redirections. If the data doesn’t match, you receive the error message above.
Solution
The issue of unmatched view-state data could be related to server configuration or session cookie. Here are the most common root causes:
If you are using ViewStateUserKey to prevent Cross-site Request Forgery (CSRF) attacks, make sure the value you assign to this variable is the same in all pages. The most common usage is that assigning session ID or username to ViewStateUserKey. Your website might be losing the session between page redirections. Check these two StackOverflow topics for details: Link 1, link 2
Redirecting the page right after setting session variables may be the issue. You should avoid using Response.Redirect in this case. Details
Antivirus software might be causing the issue. Add scanning exceptions for IIS and your application’s folders. Details
When users go through several proxies before reaching out your web server, the IP field in IIS may show only a proxy IP address instead of the actual client IP address. In this post, we will see how to find the actual client IP address in this scenario.
Long story short, you can use X-Forwarded-For request header to find the IP address of the client who sent requests. This field is not logged in IIS by default. Therefore, you need to configure custom logging in your web server.
Configure IIS to log actual client IP address
The way custom logging (also called advanced logging or enhanced logging) is configured is different based on IIS version. See the corresponding instructions below.
Looking for a list of IIS versions? Check this post out.
Which directory the custom logs are stored in?
In IIS 7/7.5/8: %SystemDrive%\inetpub\logs\AdvancedLogs In IIS 8.5+: %SystemDrive%\inetpub\logs\LogFiles
Add X-Forwarded-For column in IIS 7/7.5/8
Open IIS Manager
On server, site or application level, double click “Advanced Logging“
In the action pane on right side, click “Enable Advanced Logging“
In the action pane, click “Edit Logging Fields“
In the new window, click “Add Field“
In “Add Logging Field” window, fill out the following fields
Field ID:X-Forwarded-For, Source type:Response Header, Source name:X-Forwarded-For
Click “OK“
In the middle pane, select the default log definition “%COMPUTERNAME%-Server“. Click “Edit Log Definition“
Click “Select Logging Fields”
Select “X-Forwarded-For” from the list. Click “OK“
Click “Apply” in the actions pane
Wait for a new log file to be created. Column changes will be effective when a new log file is created. You may need to generate some traffic to fill and close the current log file.
Add X-Forwarded-For column in IIS 8.5 and newer versions
Custom logging became a lot easier with the IIS 8.5. Follow the steps below to add X-Forwarded-For column into IIS logs.
Open IIS Manager
On server, site or application level, double click “Logging”
Click “Select Fields“
In “W3C Logging Fields” window, click “Add Field“
In the “Add Custom Field” window, fill out the following fields
Field Name:X-Forwarded-For, Source type: Response Header, Source:X-Forwarded-For
Click “OK” in both open windows
Click “Apply” in the actions pane
Add X-Forwarded-For field to log actual client IP address
Wait for a new log file to be created. Column changes will be effective when a new log file is created.
Note 1: If you see a dash (“-“) in X-Forwarded-For column of the log file, it means the client didn’t use any proxies. Therefore, the client IP must be in the “c-ip” column
Note 2: You may see multiple IP addresses in X-Forwarded-For column of the log file, it means the client went through more than 1 proxy. Each proxy adds their own IP to the end of the value. The left-most IP address is the actual client IP address. Others belong to proxies the client go through.
It is highly recommended to use static IP address for servers so that users have a consistent access to the applications. However, there might be certain scenarios where you want to use dynamic IP address in web servers.
Dynamic IP address in web servers
Using dynamic IP address in web servers means using a dynamic DNS such as DynDNS and No-IP. Every time the server address changes, DNS should be notified with the new IP address to update DNS record for applications accordingly. Most of the dynamic DNS services do this by using desktop agents installed to your servers.
Assuming that you built your architecture and made necessary configuration, there are a few more things to consider:
Check with software vendors to see if this scenario is supported
In order to minimize downtime between IP changes, it is recommended to have a short TTL (time-to-live) time. Short TTL time will speed up DNS requests so that users retrieve the new IP faster in the case of a change in web server IP address. Please note that having short TTL time may affect network performance. Please discuss it with your network team before making changes.
If possible, increase the reservation time of IP addresses assigned to web servers in your DHCP to reduce the amount of IP changes over time.
Recommended TTL value
The recommended TTL value when using dynamic IP address in web servers depends on the DHCP IP lease duration in your network. If your lease duration is set to the default value (8 days for Microsoft DHCP), 1 hour TTL value (default for Microsoft DNS) is a good choice. If your lease duration is very low such as 1 or 2 hours, then your TTL value should be less than 1 hour. How much low it could be depends on your network performance. If you need to lower TTL to below 1 hour, I recommend lowering it gradually while monitoring network performance.
A good rule of thumb is to make your DDNS TTL half the amount of your DHCP lease. If the IP address lease is set to 60 (1 minute), set your TTL to 30 (30 seconds). If the IP address is 3600 (1 hour), set your TTL to 1800 (30 minutes).
Using dynamic IP address in multihomed web servers
If your server is multihomed (connected to multiple networks), you will need multiple NICs (Network Interface Controller) in your server. Each site hosted in your server can be bound to one NIC. If you have more sites than NICs, make sure to specify unique hostnames or port numbers for bindings of sites so they don’t conflict with each other. In the case of 2 sites having the bindings, one of the sites will turn off automatically.
Site bindings in IIS
Looking for a way to capture client IP address in your IIS logs? Check this post out.
“Access to the path is denied” error is one of the most common issues ASP.NET developers come across while working with network resources in their applications. There is no straightforward solution to this problem. However, there are several things you should check to solve it.
Server Error in ‘/’ Application. Access to the path X is denied. Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. Exception Details: System.UnauthorizedAccessException
“Access to the path is denied” error message
Looking for best practices for session state and cookies in ASP.NET applications? Check this post out.
Solution for “Access to the path is denied” error
The root cause is that the application pool which is hosting your web application is not able to access to the shared folder you specified in your code. Therefore, it throws “Access to the path is denied” message.
Go through the recommendations below to find out why the application pool can’t access to the network resource.
Did you give “Security” and “Sharing” permissions to the application pool identity? Make sure the account has required permissions in both tabs.
First step is to check permissions in “Security” and “Sharing” tabs
If there is no “Sharing” tab:
– Open Registry Editor (Start > Run > regedit) – Take a backup of Registry (File > Export) to an external storage – Find HKEY_CLASSES_ROOT\Directory\shellex\PropertySheetHandlers\Sharing If the folder does not exist, create it. – There should be a (Default) value with type REG_SZ and Data {f81e9010-6ea4-11ce-a7ff-00aa003ca9f6} The Data is blank? Double click on it and paste in {f81e9010-6ea4-11ce-a7ff-00aa003ca9f6}
The “Sharing” tab is still not displayed? Go to “Folder Options“. Check “Use Sharing Wizard (Recommended)“
Still not displayed? In regedit, find HKLM\System\CCS\Control\Lsa\forceguest. Modify the forceguest entry value to 0
Is impersonation enabled? In order to check it: “IIS Manager > Server name > Sites > Site name > Authentication > ASP.NET Impersonation”. If impersonation is enabled, impersonated user(s) will need permission on the shared folder.
Do you have a virtual directory? If any virtual directories are used, please make sure they use application pool identity account in their pass-through authentication settings.
More to consider
After making changes to application pool identity, please make sure to recycle , stop, and then start the application pool.
Are you able to open the shared folder in your web server by using the credentials of application pool identity account? Check it: “Start > Run > \\server-name\shared-folder”.
In the server that hosts the shared folder, check for failed logon attempts to see which user was used to access to shared folder. In order to check it: “Start > Event Viewer > Windows Logs > Security > Audit Failure“.
Find out which account is used to access to the network resource
Are you using ApplicationPoolIdentity to run your application pools? In this case, you should give permission to COMPUTER$ account on the network resource.
In conclusion, your effort to solve this problem should focus on the application pool identity account and shared folder permission. If you are still not able to solve the problem, please leave a comment here.
One way to ensure that your visitors access to your website via secure connection is to redirect HTTP requests to HTTPS by using IIS URL Rewrite module. You will find step-by-step instructions to configure IIS in this post.
Note that you may need to spend some extra effort on configuration if you have a load balancer that hosts SSL certificates (SSL offloading). Please check the last section (“If your web server is behind a Load Balancer…”) at the end of this post for more information.
Looking for an alternative way to redirect HTTP requests to HTTPS? Check this post out.
Redirect HTTP requests to HTTPS by using IIS URL Rewrite
Follow the steps below to redirect all HTTP requests to your HTTPS URL.
Make sure that your website is accessible via HTTP (Check Site Binding to make sure there is a binding for port 80)
IIS site binding for HTTP requests
In server, site or application level, go to URL Rewrite feature
Click “Add Rule(s)” in the “Actions” pane
Select “Blank rule“. Click “OK“
Create a new URL Rewrite rule
Select “Matches the Pattern” from “Requested URL” menu
Select “Wildcards” from “Using” menu
Enter * into “Pattern” field
Add a new condition with input {HTTPS}, type “Matches the Pattern“, pattern off. This condition will make sure to prevent indefinite loop from HTTPS to HTTPS. The condition will make sure the rule is executed if the request is not HTTPS
Match URL and condition for URL Rewrite rule
In the “Action” section, select “Redirect” from “Action type” menu
Enter https://{HTTP_HOST}{REQUEST_URI} into “Redirect URL” field. Click here for more information about server variables and URL parts
Redirection type and URL
Click “Apply” in the “Actions” pane
Try to access your site/application via HTTP URL and check if it is redirected to HTTPS
Web.config changes
When you add, edit or remove a URL Rewrite URL, corresponding web.config file is automatically updated. Go to application folder and open the web.config file if you want to view the changes.
If the URL Rewrite rule for redirection is not working (HTTP requests continue to go to HTTP site), I would recommend using Failed Request Tracing (FRT) to troubleshoot redirection. Here is a link for instructions to use FRT for URL Rewrite troubleshooting.
Additionally, try the recommendations below to solve the issue:
Make sure that “Require SSL” is unchecked in “SSL Settings”
Uncheck “Require SSL”
Instead of a wildcard, try using a regex in “Match URL” section (Select “Regular Expressions” from “Using” list. Enter (.*) into “Pattern” field). More information
Previous URL Rewrite rule might have cached. Try to use server variable from this list that disable kernel mode caching for all requests. You can also try disabling internal cache of rewritten URLs. Here is a list of registry values for IIS URL Rewrite.
If your web server is behind a Load Balancer…
Many companies leverage load balancers to distrubute workload amond several web servers. If this is the case in your environment, you may need to change the server variable you use in the condition of your URL Rewrite rule.
In the instructions above, we used {HTTPS} header to check the usage of HTTPS protocol. The load balancer in your network may remove this header from requests. A better practice in this scenario is to use {HTTP_X_FORWARDED_PROTO} header. Click here for more information.
Here is the web.config entry for an example URL Rewrite rule using {HTTP_X_FORWARDED_PROTO} header:
You may see “SChannel error state is 960” in Event Viewer when your web server fails to establish secure communication with clients. Users receive certification errors while you see the event log below in your server:
A fatal alert was generated and sent to the remote endpoint. This may result in termination of the connection. The TLS protocol defined fatal error code is 20. The Windows SChannel error state is 960.
Cause
This issue is caused by the different or incompatible chiper suites used in web server and load balancer. Cipher suites or chiper blocks are set of encryption methods such as RSA and DHE.
When there is a conflict or mismatch in the chiper suites used, web server cannot decrypt the encrypted request coming from load balancer and logs this error message: “The TLS protocol defined fatal error code is 20. The Windows SChannel error state is 960.”
Looking for a way to redirect all HTTP requests to HTTPS? Check this post out.
How to solve “SChannel error state is 960”
You can fix secure connection failures and make Schannel errors disappear by enabling custom chiper suite and editing the list of chiper suites used in your web server. Follow the instructions below in Windows Server:
Log onto the server using an account that is a member of the Local Administrators group
Go to “Start > Run“. Enter: gpedit.msc
In the left pane, expand “Computer Configuration > Administrative Templates > Network > SSL Configuration Settings“
In the right pane, right click “SSL Cipher Suite Order” and choose “Edit”
Click “Enabled”
Copy the content of “SSL Cipher Suites” text box and paste it notepad
Edit this list to make sure it matches the chipper suite list used in your load balancer. As a general recommendation:
Move TLS_RSA chiper suites to the top
Copy TLS_ECDHE ones after them
Remove these two chiper suites as they have known interoperability issues:
In the “SSL Cipher Suite Order” window, click “OK”
Reboot the server
Note: The list you provide in the Step 7 cannot exceed 1023 characters. In order to reduce it, make sure to give priority to the ones at top in the default cipher list. This list is ordered from strongest chipper suites to the weakest ones. Additionally, you can remove the suites that are in the black list for HTTP/2. Here is more information about HTTP/2 black list.
It didn’t work?
A less likely cause of this issue is a change in MAC (Message Authentication Code) (Source). This code is used by web server to determine that the request hasn’t changed on the way (request forgery or man-in-the-middle attack). If the web server sees that the MAC has changed, it drops the connection. Make sure that your load balancer doesn’t edit MAC value.
Another possible cause is a Windows update (KB4457129) that reportedly breaks NLB (Network Load Balancer) Cluster. Uninstalling this update or installing the patch (KB4457133) solves the issue (Source).
Two attributes come handy when you need to enforce settings in your hosting environment: overrideModeDefault and allowDefinition. Trying to override settings when these attributes are used may cause users to see HTTP Error 500.19.
Let’s say you don’t want anybody to change the default document. Use overrideModeDefault attribute in the applicationHost.config as the example below.
Looking for a way to ignore web.config files in application subfolders? Check this post out.
HTTP Error 500.19
If an application owner tries to set the default document in a web.config file, this error message will appear:
HTTP Error 500.19 – Internal Server Error The requested page cannot be accessed because the related configuration data for the page is invalid.
This configuration section cannot be used at this path. This happens when the section is locked at a parent level. Locking is either by default (overrideModeDefault=”Deny”), or set explicitly by a location tag with overrideMode=”Deny” or the legacy allowOverride=”false”.
In this case, if you try to change the default document via IIS Manager, you will receive this error message:
There was an error while performing this operation. This configuration section cannot be used at this path. This happens when the section is locked at a parent level. Locking is either by default (overrideModeDefault=”Deny”), or set explicitly by a location tag with overrideMode=”Deny” or the legacy allowOverride=”false”.
Choose which configuration files can override settings
If you want to specify which configuration file can edit which tags, use allowDefinition attribute.
For example, let’s say you want to allow server-level configuration and deny application-level configuration. In your applicationHost.config file:
When an application owner tries to set the default document in a web.config file, the error message below will appear.
Configuration section can only be set in machine.config or root web.config
The reason behind is that we specified MachineToWebRoot in allowDefinition attribute. It means that only machine.config, applicationHost.config, and root web.config file (the one in the same folder as machine.config) can override this setting.
Here are other values you can use withallowDefinition attribute (Source):
“Everywhere”
The section can be defined in any configuration level. The default value.
“MachineToApplication”
The section can be defined in the Machine.config or ApplicationHost.config file.
“MachineOnly”
The section can be defined only in the Machine.config file.
“MachineToWebRoot”
The
section can be defined in the Machine.config, ApplicationHost.config,
or Web.config file. The Web.config file is stored in the Web site root.
“AppHostOnly”
The section can be defined only in the ApplicationHost.config file.
Prevent machine.config to be overridden
For preventing machine.config settings to be overridden by child web.config files, you can use location tag with overrideMode attribute. For example:
Please note that the changes in the machine.config affects all the applications in the web server. So that make sure to test changes in development environment first.
You may want to consolidate your application’s settings in one web.config file. However, the web.config files in subfolders can override the settings of the parent folder. In order to prevent it, you need to configure IIS to ignore web.config files in application subfolders.
Here is an example of the configuration hierarchy of IIS. Note that there is a website called Site1. This website has two subfolders: SubDir1 and SubDir2 (assuming that the root application is used).
IIS configuration hierarchy
Looking for a way to prevent settings to be overridden by web.config? Check this post out.
How to ignore web.config files in application subfolders
Let’s say you don’t want the web.config files in SubDir1 and SubDir2 folders to override settings in the web.config file of Site1 folder. In order to achieve it, use allowSubDirConfig attribute in your applicationHost.config file. Here is an example:
Note: allowSubDirConfig attribute can be used only in applicationHost.config. It is not available for web.config files (Source).
Ignore web.config for certain subfolders only
It is also possible to ignore web.config files in certain subfolders only. However, these folders has to be virtual folders. In the example below, web.config files are ignored in all subfolders except the one in subDir2.
Please note that I am using <application path="/"> in the examples above. This is the root application which is created when you add a new website. If you have a specific application, make sure to use it in your config files.
Disable inheritance
What if you want to allow web.config files to be used in subfolders but you don’t want certain settings to be inherited by subfolders?
For example, your root web.config says the only default document is index.htm. However, your subfolder web.config says the only default document is iisstart.htm. If there is no such file iisstart.htm in the subfolder, root setting which is index.htm will be inherited and used. If you want to prevent root settings to be inherited, use inheritInChildApplications attribute in location tag.