"HTTP Error 401.1 - Unauthorized" when using Windows Authentication on IIS7.5

by Jon Sagara September 21, 2009 at 3:37 PM

You may have run into this error while trying to develop a site that uses Integrated Windows Authentication on Windows Server 2008 R2 with IIS7.5.  I sure did, and I beat my head against the wall for a couple of hours trying to figure it out.

It turns out to be a security mechanism built into Windows, and the workaround is simple.  Just choose one of the two methods listed in this Microsoft KB article:

You can find a more detailed explanation here:

Hope this saves you some time.

(h/t to this ServerFault.com question/answer: IE 8 Authentication Denied on local SharePoint Site)

Tags: , ,

Blog

Another code snippet of the day

by Jon Sagara July 22, 2009 at 12:45 PM

Today's a good day. Check this out:

private static Dictionary<string, string> _dict = new Dictionary<string, string>();

static MyPage()
{
    //_dict.Add("item1", "val1");
    //_dict.Add("item2", "val2");
    //_dict.Add("item3", "val3");
    //_dict.Add("item4", "val4");
}

private void InitDictionary()
{
    try
    {
        _dict.Add("item1", "val1");
        _dict.Add("item2", "val2");
        _dict.Add("item3", "val3");
        _dict.Add("item4", "val4");
    }//END TRY
    catch
    {
        _dict.Clear();
        _dict.Add("item1", "val1");
        _dict.Add("item2", "val2");
        _dict.Add("item3", "val3");
        _dict.Add("item4", "val4");
    }//END CATCH
}

So what happened here? The guy decided that initializing the static dictionary variable in the static constructor wasn't good enough, and that he needed to do it on every page request, so he created an instance method to do the initialization. For some reason, though, he kept getting an exception when initializing the dictionary after the first page view. Hmm... bettter just swallow the exception, clear the dictionary, and try again.

*slaps forehead*

Tags: , , ,

Blog

Code snippet of the day

by Jon Sagara July 22, 2009 at 9:54 AM

Just ran across this awesomeness today:

string campaignId = null;

/* ------------------------------------------------------------------------
 * see if the campaign id is in the request query params, so that a default
 * based on the url can be set.
*/
foreach (object key in Request.Params)
{
    string objCampaign = Convert.ToString(key);
    if (string.Compare(objCampaign, "campaignid", true) == 0)
    {
        campaignId = Request[Convert.ToString(objCampaign)];
        break;
    }//END IF
}//END FOREACH
/* ---------------------------------------------------------------------- */

Huh. Well, that's one way to do a Request.QueryString["campaignid"] lookup.

Tags: , , ,

Blog

ELMAH 1.0 Beta2 to 1.0 Beta3 upgrade gotcha

by Jon Sagara December 11, 2008 at 10:24 PM

In one of my projects, I upgraded ELMAH from 1.0 Beta2 to 1.0 Beta3.  I have 404 filtering turned on so that my log doesn't get flooded with 404 notifications (usually caused by legitimate, albeit a tad overzealous, monitoring applications).  Here is what the Web.config element looks like for Beta2:

<equal binding="HttpStatusCode" value="404" valueType="Int32" />

All of a sudden, when I fired up my site, I started getting a weird error message:

The Empty value type is invalid for a comparison.

It turns out that the XML schema has changed ever so slightly in 1.0 Beta3.  To fix the aforementioned error, you must change the "valueType" attribute to "type", like this:

<equal binding="HttpStatusCode" value="404" type="Int32" />

Hopefully this will save someone some pain. 

Tags: , ,

Blog

Enumerating HttpModules

by Jon Sagara August 24, 2008 at 12:33 PM

One common ASP.NET performance tip is to remove any HttpModules that your application does not use.  You can take a peek at which modules are loaded by the framework on your behalf by examining the framework's Web.config file, but how do you find out which modules are actually loaded in the current context?

Fortunately, the HttpApplication instance provides a Modules collection that you can loop through:

// Get a collection of modules loaded for the current context.

HttpModuleCollection modules = HttpContext.Current.ApplicationInstance.Modules;

 

// Enumerate the loaded HttpModules and do something with them.  For example, you can

//  create a table, listing each module by key and full type name.

// NOTE: the key is the same key specified in Web.config to add the module.

foreach (string moduleKey in modules.Keys)

{

    IHttpModule module = modules[moduleKey];

 

    // Do something with the module key and/or the HttpModule.

}

You can then use the Modules collection create a table like this:  

And boom, there you have it: a list of HttpModules that are loaded for the current context.  You can use this information to determine which HttpModules are needed by your application, and which ones you can safely remove.

Tags: ,

Blog

HttpValueCollection.ToString() generates your nice query strings

by Jon Sagara May 24, 2008 at 6:43 PM

In an ASP.NET page, if you call Request.QueryString.ToString(), you'll get a nicely formatted query string back, like this:

 my=query&string=value&foo=bar

"That's nice," I thought.  "I wonder how they implemented it.  I'll fire up Reflector and take a look."

However, when you look at the declaration of QueryString in HttpRequest, you'll see that it is of type NameValueCollection, a class that has no ToString() override; at first glance, it looks like you'd simply be calling System.Object.ToString().

Obviously, this is not what is happening, so to find out how the query string is being generated, I had to dig just a little bit deeper.  Fortunately, VS2008 lets you step into the framework.

When you step in you'll see that HttpRequest.QueryString is indeed defined to be of type NameValueCollection, but when it actually gets instantiated, it is initialized to be of type HttpValueCollection, an internal class that derives from NameValueCollection. 

HttpValueCollection has a ToString() override that does the dirty work of constructing the nice query string that you see at the top of this post.

I'm so glad that Microsoft decided to allow us to step into the framework source code.  Otherwise, I probably would have spent a good hour trying to track down the magical NameValueCollection.ToString() call.

Tags:

Blog

Response.Redirect and the ThreadAbortException, and why it’s a good thing

by Jon Sagara April 5, 2008 at 6:28 PM

A couple of months ago, I ran into a problem where I was seeing a bunch of ThreadAbortExceptions showing up in my logs.  It didn’t take long to track down why – I was calling Response.Redirect from within a try/catch block in my ASP.NET code-behind page, and the catch block was catching the ThreadAbortException and writing it out to the log.  But why was the ThreadAbortException being generated? 

It turns out that Response.Redirect, when called with just the URL, or with the URL and a Boolean value of true, calls the Response.End method.  Response.End then calls Thread.Abort on the current thread, and, assuming that the page is in a cancellable state, this method throws the ThreadAbortException, alerting the framework that it is time to stop this thread, and NOW.

Why is this a good thing?

Let’s step back a bit and look at the recommended workaround for dealing with the ThreadAbortException.  Googling for an answer yields many suggestions to call Response.Redirect and pass the Boolean value false as the second, optional parameter.  This effectively suppresses the ThreadAbortException, preventing it from being caught and potentially logged as an error.

All is well and good, right?  Isn’t this what we want?

Not quite.

One side-effect of suppressing the ThreadAbortException is that any code after Response.Redirect is still executed.  This includes any event handlers in the page lifecycle that have yet to execute.  This is a waste of system resources, particularly if any of these event handlers contains resource-intensive code.

For the sake of illustration, let’s assume that our page, Default.aspx, has event handlers for most of the Page’s events:

  • Page_PreInit
  • Page_Init
  • Page_InitComplete
  • Page_PreLoad
  • Page_Load
  • Page_LoadComplete
  • Page_PreRender
  • Page_PreRenderComplete
  • Page_SaveStateComplete

Let’s further assume that each of these event handlers contains a resource- and time-intensive operation.  It could be a database call, a network call, or a batch image manipulation.  Whatever it is, it requires a lot of resources and a lot of time.

Each event handler will append a string to a StringBuilder member variable called _EventsFired.  Immediately preceding the call to Response.Redirect, _EventsFired will be stored as a Session variable so that the error page, Error.aspx, can display which methods were called.  The Redirect will occur in the Page_Load method; the user will be sent from Default.aspx to Error.aspx, which will then display the contents of _EventsFired.

Here is the code listing of Default.aspx’s Page_Load event handler:

protected void Page_Load (Object sender, EventArgs e)

{

    _EventsFired.Append ("Page_Load called.  Resource-intensive operation executed.<br />");

 

    try

    {

        Session["ErrorMessage"] = _EventsFired;

 

        Response.Redirect ("Error.aspx", false);

        Context.ApplicationInstance.CompleteRequest ();

    }

    catch (Exception ex)

    {

        _EventsFired.Append (ex.ToString ());

    }

}

Notice how we are passing false as the second parameter of Response.Redirect, meaning that we will prevent a ThreadAbortException from being thrown. 

Here is the output from Error.aspx:

Page_PreInit called. Resource-intensive operation executed.
Page_Init called. Resource-intensive operation executed.
Page_InitComplete called. Resource-intensive operation executed.
Page_PreLoad called. Resource-intensive operation executed.
Page_Load called. Resource-intensive operation executed.
Page_LoadComplete called. Resource-intensive operation executed.
Page_PreRender called. Resource-intensive operation executed.
Page_PreRenderComplete called. Resource-intensive operation executed.
Page_SaveStateComplete called. Resource-intensive operation executed.
Render called.

Page execution did not stop at Page_Load, even though we told the Application to complete the request!  In all likelihood, this is not the desired behavior, especially if any of the post-Load event handlers contains time-consuming or resource-intensive operations.

Now let’s modify Default.aspx’s Page_Load event handler to call Response.Redirect without suppressing a ThreadAbortException from being thrown:

protected void Page_Load (Object sender, EventArgs e)

{

    _EventsFired.Append ("Page_Load called.  Resource-intensive operation executed.<br />");

 

    try

    {

        Session["ErrorMessage"] = _EventsFired;

 

        Response.Redirect ("Error.aspx");

    }

    catch (Exception ex)

    {

        _EventsFired.Append (ex.ToString ());

    }

}

Here is the output from Error.aspx (remember, this is the list of events that fired during the processing of Default.aspx):

Page_PreInit called. Resource-intensive operation executed.
Page_Init called. Resource-intensive operation executed.
Page_InitComplete called. Resource-intensive operation executed.
Page_PreLoad called. Resource-intensive operation executed.
Page_Load called. Resource-intensive operation executed.
System.Threading.ThreadAbortException: [snip] \Default.aspx.cs:line 45

It’s almost what we want, but notice that we “logged” the ThreadAbortException.  We need a way to exclude that from being logged. 

Let’s modify Default.aspx’s Page_Load event handler one more time:

protected void Page_Load (Object sender, EventArgs e)

{

    _EventsFired.Append ("Page_Load called.  Resource-intensive operation executed.<br />");

 

    try

    {

        Session["ErrorMessage"] = _EventsFired;

 

        Response.Redirect ("Error.aspx");

    }

    catch (System.Threading.ThreadAbortException)

    {

        throw;

    }

    catch (Exception ex)

    {

        _EventsFired.Append (ex.ToString ());

    }

}

Here is the output from Error.aspx:

Page_PreInit called. Resource-intensive operation executed.
Page_Init called. Resource-intensive operation executed.
Page_InitComplete called. Resource-intensive operation executed.
Page_PreLoad called. Resource-intensive operation executed.
Page_Load called. Resource-intensive operation executed.

Success!  Finally, the desired result!

  • The page stopped processing when it was supposed to, right after the call to Response.Redirect.
  • Event handlers later on in the page lifecycle were not unnecessarily executed.
  • The ThreadAbortException was not “logged” by our catch block.  Instead, it was explicitly caught and rethrown up the stack.

So there we have it.  Suppressing the Response.Redirect-generated ThreadAbortException can be a bad thing, particularly if there is a lot of resource-intensive code left to execute after the redirect.  To prevent those pesky ThreadAbortExceptions from showing up in our log files, all we have to do is explicitly catch them and rethrow them.  On busy sites, this can help to conserve scarce resources.

Used properly, ThreadAbortException is your friend.

Update 2007-08-01 07:44

Of course, I could have moved the Response.Redirect outside of the try/catch.  However, the code that prompted the writing of this article is legacy production code that can't be modified at my whim, hence the need for this approach.

Update 2008-04-05:  Moved over from jonsagara.com.

Tags:

Blog