Skip to the content Back to Top

Setup

An ASP.NET web application set to use Windows authentication where the web.config allows/denies authorization based on Windows roles, which references the BUILTIN\Administrators role specifically.

Your account is in the BUILTIN\Administrators group. The web application is running on a Windows OS with User Account Control [UAC] enabled. (hint HINT.)

Here's an example taken straight from official Microsoft Patterns and Practices: How To: use Windows Authentication in ASP.NET 2.0.

win_auth_example

Symptom

Even though your account is in the BUILTIN\Administrators group - you checked three times, pinching yourself in case you were dreaming - you cannot authenticate to get in to the web application. Instead, you get 401.2 errors.

401.2

You know your credentials are correct, because if you deliberately screw up your password, you get a 401.1 error. If you allow your specific account (DOMAIN\frustratedguy) in web.config, you can authenticate as normal.

It's as if the app doesn't think you are a member of the BUILTIN\Administrators role at all...

Cure

In fact, as far as the app is concerned, you are not a member of BUILTIN\Administrators. UAC has cast you out from that divine realm, and you no longer hold the keys to heaven.

using System.Web.Security
 
Roles.GetRolesForUser(User.Identity.Name);

Listing roles might get you a list like:

None,Everyone,HomeUsers,BUILTIN\Users,NT AUTHORITY\NETWORK,NT AUTHORITY\Authenticated Users,NT AUTHORITY\This Organization,NT AUTHORITY\NTLM Authentication

No BUILTIN\Administrators. Allow another of those roles in web.config and your credentials will authenticate.

Myself, I didn't know how UAC actually worked. I knew that it didn't let me operate in the context of Administrator unless explicitly told to do so, but I didn't realize that meant that a role check would fail to find me in the Administrators group. Live and learn.

When programming, if you don't fully understand some technique, do not use it. And don't mistake intellisense for intelligence.

Case in point.

I wanted to know whether a particular barcode was contained in a list of barcodes. If not in that list, add to another list:

string barcode = "12345";
int index = barcodeList.BinarySearch(barcode);
if (index < 0)
{
    otherList.Add(barcode);
}

Ooh, binary search. Visual Studio intellisense reports:

List<T>.BinarySearch(T item): Searches the entire sorted List<T> for an element using the default comparer and returns the zero-based index of the comparer.

Sounds good to me. Sign me up!

One teary-eyed debugging session later, as barcodes are being reported NOT found that SHOULD be found, I learn the full truth from MSDN:

BinarySearch() return value is the zero-based index of item in the sorted List, if item is found; otherwise, a negative number that is the bitwise complement of the index of the next element that is larger than item or, if there is no larger element, the bitwise complement of Count.

Oh... shazbot.

Why didn't I just use List.Contains?

string barcode = "12345";
if (!barcodeList.Contains(barcode))
{
    otherList.Add(barcode);
}

Because. I am an idiot.

 

Fortunately, I didn't waste too much time on this runtime error before googling and finding http://www.wackylabs.net/2005/12/strange-aspnet-20-error/. It turns out a compile time error is not thrown when there's a naming collision between ASP.NET 2.0's Page.Title property and a server-side control given the ID of "Title". Instead, the page in question will build no problem, but won't run. In my case I had given the ID of "Title" to one of a TON of new textboxes on a page I was working on in an ASP.NET 2.0 application.

Why this is able to make it past the compiler is beyond me.

It was one of those days where I had so much junk on my computer that I decided to reformat it and start fresh. It was a "wonderful" feeling after the whole long process was complete (I since then made a recovery backup archive of my clean system). However, my feel-good story hit an interesting turning-point and started to turn into a B-rated drive-thru horror flick when I ran into a problem while running a .NET web site locally on my computer (cue the dramatic musical score): Server Application Unavailable The web application you are attempting to access on this web server is currently unavailable. Please hit the "Refresh" button in your web browser to retry your request. ...skipping the excessive violent fight and car chase scenes...fast forwarding to the happy ending... Here are the articles that saved the day from http://www.ironspeed.com (cue Tonto and the calvary):
Verifying the .NET Framework was Installed after Microsoft IIS Setting the ASP.NET State Service to Run Automatically
I "think" Microsoft's Automatic Updates must have installed the .NET Framework automatically before I was able to install IIS from Windows' Add/Remove Windows Components function (this can happen when you leave your newly reformatted computer running all day to download updates), OR ...and quite possibly...staying awake till 3am impaired my judgment and I just downloaded and installed all updates that I could possibly get. Who knows the real reason?!?!...it's fixed...and now I am waiting for the inevitable hollywood-cash-grab sequel.

I switched from VB.NET to C# a few months ago because of the JetBrains Resharper Visual Studio add-in.

C# has been a joy for the most part. I am occasionally stumped because it is stricter than VB.NET, but working through such challenges makes me understand the C# language and .NET framework better.

Ted and I, and I guess other asp.net developers, work with query strings a LOT. I discovered a couple of new methods in .NET 2.0 that are helping me out with the HttpRequest.QueryString collection.

String.IsNullOrEmpty(string): bool

A typical scenario is to init a string, pass it a query string value, and then check to see that the string has a value. I'm always trying to remember whether a non-existent query string key returns null, or an empty string. Or if the key is there but has no value, is that null or an empty string? With String.IsNullOrEmpty, I don't have to think:

string CheckId = Request.QueryString["ID"];

if (string.IsNullOrEmpty(CheckId) == false)

{

    //do stuff

}

Int32.TryParse(string, out Int32): bool

In the code example above, I want an ID value, which I need to be a integer. I want to test that it is a number before proceeding, and I also want to actually convert it to an integer. In the past I would use VB.NET's IsNumeric, and then Int32.Parse(string) in a try/catch block. What a pain. Int32.TryParse simultaneously tests the input string for integericity, returning a boolean, and outputs the integer result (zero if the string can't be parsed):

int i;

if (int.TryParse(CheckId, out i))

{

    //do stuff with i

}

Let Us Help You!

We're Librarians - We Love to Help People