February 2007

Monthly Archive

The Evil ASP.NET Tab and other adventures with MMC

Posted by on 27 Feb 2007 | Tagged as: .NET, ASP.NET, IIS, SysAdmin

Today I encountered a strange problem with IIS6 restarting without notice on a server that had recently had the .NET Framework 2.0 installed on it. In our particular case the problem was made worse by the fact that the IIS restart was unsuccessful leaving the server in a some what crippled state. We traced the problem to clicking on the ASP.NET in the IIS Management MMC, not making any changes to the settings, then clicking OK on the properties dialog.
Usually making a change to the version of ASP.NET will cause a restart of IIS (and there are alternative ways that avoid the restart), however in this case it seems as though just viewing the tab and then clicking OK was enough to cause ASP.NET to restart the IIS Service. I’ve still not discovered precisely why this is happening, but for the time being I wanted to implement a work around to avoid the problem by disabling the ASP.NET Tab.

I thought doing this would be easy, after all enough people seem to have problems with the tab not being there. Common causes of the tab being missing seem to be running the IIS MMC on x64, or having installed an earlier beta of .NET 2.0. The fixes in most cases seem to be modifications to the registry or re-running aspnet_regiis -i to re-register ASP.NET.

While it is possible that by fiddling with the registry I could break the ASP.NET tab that didn’t seem to be a good solution, so I carried on digging. It turns out that the ASP.NET Tab is implemented as an MMC Snap-in extension, and can be disabled with two clicks of the mouse once you’ve found the setting. So, to disable the ASP.NET tab within the ASP.NET management MMC:

  1. Start the MMC console (Start > Run > ‘mmc’ OK)
  2. Open the IIS management mmc (Console > Open > ‘%windir%\system32\inetsrv\iis.msc’ OK)
  3. Edit the Snapin Settings (Console > Add/Remove Snap-in)
  4. Choose the Extensions Tab, and disable the ‘ASP.NET Management Extension’ by unticking ‘Add all Extensions’ and the unticking the ‘ASP.NET Management Extension’.
  5. OK the changes and then save the console (Console > Save )

Now when you start the IIS Manager the ASP.NET tab won’t be there.

Sadly the tab is still there in the Computer Management MMC (Computer Management > Services And Applications > Internet Information Services), and looking at the computer management MMC in the same way as above does not yield the same choice of Extensions, so if anyone knows how to influence Computer Management in the same way, please let me know!

Keys with multiple values in appSettings

Posted by on 08 Feb 2007 | Tagged as: .NET, C#, Development

One of my pet hates about the default ApplicationSettings within the .NET framework is the inability to work with multiple values for the same key in the config file (app.config or web.Config)

<appSettings>
   <add key="key" value="value1" />
   <add key="key" value="value2" />
   <add key="key" value="value3" />
</appSettings>

The built in support suggests that it would be possible to call the System.Configuration.ConfigurationSettings.AppSettings.GetValues("key") method to return a string[] containing all the values for the specified key. Unfortunately, the built in support only returns the last value defined (in my example above, “value3″)

Thankfully there are a number of very easy to use replacements for the standard support, and a variation on the solution proposed in Diego Mijelshon’s article How to make AppSettings work with multiple values for a key is one of the first things that I add into any application which will make use of AppSettings.

Code Project has a number of good articles about extending the default AppSettings support, two others which caught my eye are:

Web Service Connection Problems

Posted by on 06 Feb 2007 | Tagged as: .NET, C#, Development, IIS, SysAdmin, Web Services

Setting the scene

Web Services are very simple to consume using .NET code, and its all to easy to forget what is actually going on when you add that Web Reference to your project in Visual Studio. Once you’ve entered the URL for you web service and clicked the Add Reference button, Visual Studio requests the service description WSDL file, and code generates classes to represent the data and the web service methods. I found delving into this generated code taught me quite a lot about the way XML serialization and web services actually work.

Behind the scenes the web service proxy uses classes in the System.Web.Services.Protocols namespace to actually perform the calls to the service, and these calls end up as System.Net.WebRequests containing the correctly encoded data that makes up the message.

Problems with Web Requests

Quite a lot of the problems with web services I encounter during deployment are actually problems with the System.Net.WebRequest. The most common cause of problems seems to be problems where web access is provided via some form of HTTP Proxy Server, and this typically results in an exception of the form:
[WebException: The underlying connection was closed: Unable to connect to the remote server.]

If you have access to the machine running your application its a very good idea to check if the machine can make a request to your Web Service endpoint using a web browser. This also allows you to check the settings to see if web traffic is passing through a proxy – failing this, check with the people responsible for the network.

If you find that there is a proxy involved, there are a couple of strategies available to resolve the problem.

  • Make Changes in machine.config to affect all applications
    machine.Config is one of the .NET framework’s main configuration files, and can be found in the framework directory. Settings in the defaultProxy section with that attribute usesystemdefault="false"allow system wide setting of a default proxy server overriding an OS setting:<configuration>
        <system.net>
            <defaultProxy>
                <proxy
                     usesystemdefault = "false"
                        proxyaddress="http://proxyserver:port"
                        bypassonlocal="false"
                    />
                </defaultProxy>
            </system.net>
        </configuration>
  • Configuration change for your application only
    If you don’t control the machine your application is running on then its unlikely you will be able to make changes to machine.config, but thankfully the above section will also work in your web.config or app.confg files
  • Programmatic Solution
    You can set the proxy settings in code:

    using System.Net;

    MyWebService ws= new MyWebService();
    WebProxy proxyObject = new WebProxy("http://proxyservername:port", true);
    MyWebService.Proxy = proxyObject;
    MyWebService.MyWebMethod();

All of the above methods apply to Web Service classes and also the WebRequest Classes

But what if there isn’t a proxy?

I discovered this week that the proxy problem is not the only cause of a web application which calls a web service throwing the exception:
[WebException: The underlying connection was closed: Unable to connect to the remote server.]

The next step I took in investigating this problem was to create two very simple test applications – one ASP.NET based like the code I was having problems with, and another a simple console application I could run as Administrator on the machine in question.

Test.aspx

<%@Page language="c#"%>
<%
System.Net.WebRequest r = System.Net.WebRequest.Create("http://av.com");
string resp = new System.IO.StreamReader(r.GetResponse()
                   .GetResponseStream()).ReadToEnd();
Response.Write("Response:");
Response.Write(resp);
%>

test.cs

using System;
using System.Net;
using System.IO;

public class Test
{
   public static void Main()
   {
      WebRequest r = WebRequest.Create("http://av.com");
      string resp = new StreamReader(r.GetResponse().GetResponseStream()).ReadToEnd();
      Console.WriteLine("Response:");
      Console.WriteLine(resp);
   }
}

Both of these make WebRequests to the Altavista search engine, and therefore tested requests out onto the Internet, returning the HTML from the Altavista homepage. As expected the ASP.NET based version gave the same exception as before, however the console application revealed not one, but two exceptions:

Unhandled Exception: System.TypeInitializationException: The type initializer for "System.Net.Sockets.Socket" threw an exception.

---> System.Net.Sockets.SocketException: An operation on a socket could not be performed because the system lacked sufficient buffer space or because a queue was full
  at System.Net.Sockets.Socket.InitializeSockets()
  at System.Net.Sockets.Socket..cctor()

Which is followed by a more standard looking timeout exception

[WebException: The operation has timed-out. ]

Changing the test code to request a page from the local IIS server to no effect confirmed that it was unlikely that this was an HTTP proxy problem.

Quite a lot of searching the web, lead me towards an Microsoft Bulletin Bulletin
BUG: You receive a “The operation has timed-out” error message when you access a Web service or when you use the IPAddress class
which sounded somewhat familiar, and suggested that the problem might be caused by have more than 50 protocol bindings . Running the enum.exe utliity linked in the MS article revealed that this machine had over 100 bindings. Performing the same check on a number of other machines revealed that a more typical value was about 20, so something was not quite right with this machine. Removing some unneeded protocols from the networking setup resolved the issue, with both console application and ASP.NET test page returned the expected HTML, and most importantly the failing web service calls in the web application now works.