Access Denied on Web Service Calls

This question has been asked of me enough that I feel it's worth a blog.  It's not the this solution is unique, but I'm hoping that Google will do its thing with respect to getting the word out to people who need it.

First of all, the symptom we're addressing is an HTTP status code of 401 (Access denied) that is returned when making a call to a web service method through a proxy class. The solution is quite simple.  Actually, to be more precise, there are two solutions, with the best one depending (of course) on your goals. First, the virtual directory in which the web service is running can be modified to allow anonymous access.  Alternatively, the credentials associated with the current user can be attached to the web service call by including the following statement prior to the method call.

ws.Credentials = System.Net.CredentialCache.DefaultCredentials;

Now that the solution has been addressed, let's take a brief look at why the problem exists in the first place.  When a request is made from a browser to a web server, the server may require some form of authentication. It is possible that the initial request can include the authentication information, but if the server doesn't see it, then an HTTP 401 status code is returned.  Included in the response is an Authenticate header which indicates the type of authencation that is expected and the name of the realm being accessed.  The browser then reissues the request, providing an Authentication header including your current credentials.  If that request fails (returns another 401 status), the browser prompts you for a set of credentials.  This is a sequence of events that all of you have seen before, even if the underlying rationale is new information.

However, when you make a web method call through the proxy class, the handshaking that goes on with respect to authentication doesn't take place. It's the browser that does this magic and the proxy class doesn't include that code. The result is that the client application receives the access denied status. So you need to configure the virtual directory to not reject unauthenticated requests (by turning anonymous access on) or provide your own set of credentials with the call (by populating the Credentials property on the proxy class).

VS Live Orlando: Building "Operations-Friendly" ASP.NET Applications with Instrumentation and Logging

Yes, it's the longest title of all VS Live Orlando presentations! It's a big topic and it deserves a big name.

I'm heading out Monday night to hurricane country to deliver this talk on Tuesday morning. I like this topic because when you get into it, it's like an onion. It doesn't look like something terribly sophisticated but as you get into you find there are more and more layers to peel back.

Opening a File by Association

For a simple application, which I hope to share with you shortly, I needed to be able to launch the application associated with a particular file type.  For example, if you had a file called 'test.log' and the '.log' extension was associated with UltraEdit32, I wanted to launch UltraEdit32 and load up test.log.  While I could have located the file association in the registry and launched the application, there is an easier way.  Use the Process class to execute “test.log” as a command and let Windows do the rest.

System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.EnableRaisingEvents = false;
proc.StartInfo.FileName = “test.log“;
proc.Start();

I can't get over how nicely the little things in the .NET Framework fit together.  It's almost like someone...what's the word...designed it ;)

Building Mobile Applications, Metro Toronto .NET Users Group

Tomorrow night I'm presenting at the downtown Toronto .NET users group - topic Pocket PC development with the CE framework. I'll have a new HP 4700 device with a VGA resolution screen for folks to take a look at - courtesy of your friendly neighborhood HP rep. I'll also have my trusty 5650 with the old form factor for you to play around with. Hope to see you there.

Details: http://www.objectsharp.com/oNewsUpdate/ReadingFullStory.aspx?StoryNum=-28

Hiding the Startup Form

As part of my holiday weekend, I created an intray application aimed at tracking the build status in a continuous build environment.  To complete the aesthetics of the app, I wanted my initial form to be hidden immediately upon startup.  A quick Google of the problem found the following MSDN page.

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vbcon/html/vbtsksettingformtobeinvisibleatitsinception.asp

What concerned me is that it mentions that, without using Application.Run, there is the possibility that certain functionality wouldn't work.  I never liked wondering what *might* go wrong with my code (I have too much problem with what *does* go wrong).  With a little bit of experimentation, I found that the following variation gives me the desired result.

public static Main(string[] args)
{
   YourForm form = new YourForm();
   Application.Run();
}

Additionally, when you are exiting the form, it is important to remember that the message pump initiated by Application.Run needs to be shut down.  As a result, you need to include the statement 

Application.Exit();

as part of the form shutdown process.

Shorthorn Longhorn

So this will cause a few blogs. I have just heard that....

  • Longhorn slated for 2006. Longhorn server 2007.
  • Winfx, and Avalon are coming to windows xp in 2006. Indigo as well - and on Windows 2003 as well. These are all part of WinFx that is going to be extremely important for .NET developers and companies wanting to take advantage of these improvements.
  • Winfs is leaving longhorn (post release). So that means ObjectSpaces and the Microsoft Business Framework too.

Wow. Never a dull moment. I'm attending a briefing with Jim Allchin in an hour so I might have more I can tell.

But will we also see a delay of ObjectSpaces or the Microsoft Business Framework until after the longhorn release. Those have been recently tied into WinFs - but no specific announcements about that - and I wouldn't be surprised if that changed soon. 

Avalon and Indigo on Windows XP

If you haven't yet heard the announcement, Microsoft is planning on having Avalon and Indigo running on Windows XP.  This might seem like old news, but until now, there was no confirmation of backwards compatibility.  As well, the target date for the client portion of Longhorn is 2006.  This target date is not new, however news that the server version of Longhorn shipping in 2007 is.  To see the press release, check out the following link:

http://www.microsoft.com/presspass/press/2004/Aug04/08-27Target2006PR.asp

Getting the App Config Path

Continuing my weekend Internet cruising, I also came across a piece of information that I had wondered about, but never found.  How to get the path to the .config file being used by a .NET application.  Apparently, this information is available through the AppDomain. Specifically, the following method retrieves said path:

AppDomain.CurrentDomain.GetData("APP_CONFIG_FILE")

The things that are available on the Internet if you know where to find them.  Or, in my case, just randomly stumble across them.

Modifying a cell in a DataSet

This post also falls under the “I need to remember this” category, because it's not the first time I've run into the situation.  I was running a quick test of something relatively unrelated (the functionality of the RowUpdating event) when I needed to modify a particular element in a DataSet. The line of code I created to do this was

ds.Tables[0].Rows[0].ItemArray[1] = “Test”;

Seems innocuous enough.  And if you're at all familiar with ADO.NET, this would seem to be a reasonable approach.  In fact, Microsoft even says this is the way to do it here (check out the first C# code...the VB.NET code works fine).  Unfortunately, both Microsoft and reason are mistaken. The correct way to update a cell is as follows

ds.Tables[0].Rows[0].Item[1] = “Test”;

or

ds.Tables[0].Rows[0][1] = “Test”;

The reason for fact that setting the element on ItemArray failing has to do with the actual definition of the ItemArray property.  According to the documentation, ItemArray “gets or sets all of the values for a row through an array”.  In other words, ItemArray is intended to be used an array at a time, not an element at a time. In fact, the getter on ItemArray is actually creating a copy of the values in the DataRow (if you need proof, use a tool like Reflector to check out the code).  So when you do the assignment, you're changing the value of a copy of the values in DataRow, not the underlying value itself.  Which, in turn, means that any DataAdapter.Update performed on the DataSet won't see the change.

Just something to keep in mind.

New Service Packs for 1.0 & 1.1 .NET Frameworks imminent

.NET Framework 1.0 SP3 and 1.1 SP1 are in tech preview at the moment. Had a nagging bug and want to know if it's fixed?

The contents & links to Tech Preview Downloads can be found here:

http://msdn.microsoft.com/netframework/downloads/updates/sptechpreview/default.aspx