26 October 2007

Things I learned about ASP.Net web services today

I have been writing a Web Service in C#/ASP.Net that manipulates PDFs, requires a long timeout period, and needs to perform some IO (moving files and cleaning up after itself). None of these things in themselves is difficult, but combined make for some hours of research.

Here are a few lessons I learned today, listed here for later use:

Lesson #1: File IO is not difficult to implement on a local XP machine, but can be tricky to get working. The application I am using uses the System.IO namespace, File.Move method, to rename files. When I first tried to get the application running, ASP kept returning the error 'Access denied to path.' A quick search around the net displays all kinds of answers, from editing the registry to granting IIS permission to the folder to adding the directory in question as a virtual directory.

For me, the answer turned out to be much more simple. My machine already had full access to the directories, so what was the source of the error. What I needed to do was add the identity tag to the Web.config file. The actual code is as follows (from an old MSDN article):

<configuration>
<system.web>
<identity impersonate='true'/>
</system.web>
</configuration>

I added this setting and then removed the permissions I had added before, and the File IO still worked on my machine. The implication is that the web service will impersonate the caller and have the same rights on the box as the rights of the calling application. Or anyway, that is what I imagine since the Web.Config documentation and my understanding of Windows security is lacking.

A long Microsoft explanation of impersonation can be found here.

Lesson #2: What happens if the service takes a long time to process?
If a service takes too long to process, the client will time out and you will either recieve an 'html/utf' error or a timeout error. The way to resolve this is as follows:
  1. In the client, add the System.Threading namespace to your calling class. When declaring your service variable, set the Timeout property of the Service to Timeout.Infinite, or the outer edge of what you expect the timeout to be in milliseconds. I usually use a calculation for millisecond settings, so I can quickly make the change. For instance, to set the Timeout property to 3 minutes, I would use myService.Timeout = 1000 * 60 * 3; 1000 milliseconds = 1 second, 60 seconds = 1 minute, for 3 minutes.

  2. The Web.config file will also need to be edited on the server. Use the httpRuntime tag and set the executionTimeout attribute to get the desired number of seconds in the timeout. No calculation is allowed as above. This tag also goes inside the system.web tag. Full Microsoft documentation of this tag can be found here.
I should mention that this application is an intranet application, so by definition all users have to be on a Windows network for these settings to be relevant to another environment.