Showing posts with label iis. Show all posts
Showing posts with label iis. Show all posts

11 April 2011

IIS6 to IIS7 - Catching Ajax errors

The way Ajax errors are sent to the browser has changed between IIS6 and IIS7. Errors used to be sent automatically and you could parse the XML on the client. Now, the developer is required to do a little more work because IIS traps the error and stops code execution before reaching the end of the method.
For example, the Ext JS Ajax call takes an object with 5 parameters: method, url, params, success and failure. The last parameter is a callback function that is executed if the server sends back a failure.
The good news is that you have to make a small change to the server-side code (only). Another piece of good news is that the code is generic - the snippet will work with most web methods.
To make it work, create a try... block around the code that may throw an error. (This example is written in C#.) Next, add the following catch block:

catch (Exception e) {
HttpResponse Response = HttpContext.Current.Response;
Response.StatusCode = 500;
Response.Write(e.Message);
HttpContext.Current.ApplicationInstance.CompleteRequest();
Response.End();
}

The code above intercepts the error and returns it to the client. If you already had Ajax code listening for failure, you will not have to change the client side at all.

Note: Special thanks to this blog post by Rick Strahl.

28 February 2011

Fixing IIS Error 401.2 - Unauthorized Access

I have developed several applications in Ext JS and recently noticed that all my server calls for a grid made two calls to the server. The first call was a fail, but the second call succeeded. This happens so quickly that the user is not even aware of the issue, but I wanted to track it down anyway.

I examined the HTTP traffic using Fiddler, and found this error in the header of the failed call:


You are not authorized to view this page
You do not have permission to view this directory or page using the credentials that you supplied because your Web browser is sending a WWW-Authenticate header field that the Web server is not configured to accept.
---

Please try the following:

  • Contact the Web site administrator if you believe you should be able to view this directory or page.
  • Click the Refresh button to try again with different credentials.
HTTP Error 401.2 - Unauthorized: Access is denied due to server configuration.
Internet Information Services (IIS)

---

Technical Information (for support personnel)

  • Go to Microsoft Product Support Services and perform a title search for the words HTTP and 401.
  • Open IIS Help, which is accessible in IIS Manager (inetmgr),
    and search for topics titled About Security, Authentication, and About Custom Error Messages.


This problem was happening in IIS6 on Win2K3, but I actually observed it happening on II7 on Win2K8 R2. I found a clue on this website, which recommended changing the order of IIS's method for authentication. Unfortunately for me, this post talked about a UI fix that does not appear to be valid for my version of IIS.

Changing the order of authentication is the answer however, although it needs to be done directly in the ApplicationHost.config file. The fix for this issue is as follows:
  1. Find the ApplicationHost.config file in C:\Windows\System32\inetserv\config.
  2. Copy file to new folder.
  3. Open config file in Notepad. Search for NTLM. You will find it in the windowsAuthentication/providers section of the file. The value "Negotiate" will be listed ABOVE NTLM
  4. Copy the entire XML line so that NTLM is the first on the list of providers.
  5. Restart the World Wide Web Publishing service. Once that is done, the issue goes away.

01 April 2008

Resolve ASP Error: Could not create a Disk Cache Sub-directory for the Application Pool

This is a permission problem. Give IIS_WPG and NETWORK SERVICE permission to access the following directories:

%systemroot%\Help\IISHelp\Common
%systemroot%\System32\Inetsrv\ASP Compiled Templates*
%systemroot%\IIS Temporary Compressed Files


* Compiled templates not available on the server I am working with. So I gave permission to the Inetsrv account.

26 March 2008

Put simply: Encrypting ASP.Net Web.config Connection Strings

I want to take the time to quickly explain what I have learned about ASP.Net / web.config element encryption. In this case, I wanted to deploy a web application to 4 servers and individually encrypt the connection strings for each application.

The problem was that while it worked well on the first server, the second server either refused to encrypt the connection string or the application would throw an error and crash before delivering the page.

Prepare the Application Server

Grant web access to the application folder so that the encryption engine can get access to the file. To do that, go onto the web server and find the physical directory where the application resides.

Right-click on the folder and choose Properties. Choose the radio option 'Share this folder'. The Edit Alias form will appear. Leave the default values (Access Permissions: Read & Application permissions: Scripts). Push ok and apply to save the settings.

Prepare the Connection String

The next step is to create your web.config and add connection information.

Connection String Example

<connectionStrings>
<remove name="LocalSqlServer" />
<add name="Cn_Name" connectionString="Data Source=Server_Name;Initial Catalog=Database_Name;User Id=User_Id;Password=Password;" />
</connectionStrings>

Add configProtectedData Element

The connectionStrings element is a descendant of the configuration element. In the configuration element, you will need to add the configProtectedData / providers / add elements and make a reference the System.Configuration.RsaProtectedConfiugrationProvider. Be sure that the PublicKeyToken is accurate. You can match it to the token in the Assembly directory.

The compiler (in Visual Studio 2005 at least) does not recognize the keyContainerName or useMachineContainer elements. They get underlined by VS, but the errors are ignored. Don't be a purist - just add them.

ConfigProtectedData Example

<configProtectedData>
<providers>
<add name="Name_of_Provider"
type="System.Configuration.RsaProtectedConfigurationProvider,
System.Configuration, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a,
processorArchitecture=MSIL"
keyContainerName="Name_of_key"
useMachineContainer="true" />
</providers>
</configProtectedData>

You may see some documentation saying to add a xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0 attribute to the configuration element. In my experience, this just complicates the final encryption process, so I do not recommend it. On the other hand, it removes the compiler issues noted above. But you are on your own for figuring out the final command line arguments, because you will have to reference the namespace in your commands - something I don't have time to think about or figure out.

Find Out the ASP / IIS Service Account

You then need to find out which service account IIS is running under. I did this by turning impersonation off and then creating a simple ASPX page to find the identity. Execute that page and record the value returned on the page.

ASP Code to find IIS Service Account
<%@ Page Language="C#" %>
<% Response.Write(System.Security.Principal.WindowsIdentity.GetCurrent().Name); %>

Again - if you have impersonation set to true in your web.config, turn it off, otherwise it will just return the impersonated account, which won't help you when executing the encryption command lines.

The Encryption Command Lines

Once you have performed all these steps, you are ready to create your batch file to encrypt the connectionStrings section of the web.config. Just copy these lines into

C:\WINNT\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis.exe -pc "Name_of_key" -exp
C:\WINNT\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis.exe -pa "Name_of_key" "[ASP Identity]"
C:\WINNT\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis.exe -pe "connectionStrings" -app "/Application_Name" -prov "Name_Of_Provider"

Where:

  • Name_of_key is from the web.config above.
  • ASP Identity is returned from the sample ASPX page. In my case it was "NT AUTHORITY\NETWORK SERVICE"
  • Application_Name is the name of the ASP.Net application where the web.config resides.
  • Name_Of_Provider is the provider name from the web.config above.

References: