Application Start su IIS7 in Integrated Mode

La settimana scorsa mi sono imbattuto in uno “strano” errore  sollevato da Internet Information Service 7 (IIS7): nello specifico veniva sollevata una System.Web.HttpException con il seguente messaggio:

Request is not available in this context

L’eccezione veniva sollevata dall’ Application_Start del Global.asax, in quanto cercavo di accedere all’HttpContext per effettuare il log di avvio dell’applicazione; in realtà non avevo necessità di accedere all’ HttpContext, ma il logger che utilizzavo di default ad ogni chiamata verificava che il Context non fosse nullo e nel caso aggiungeva info sull’url richiesto (Referrer, ecc), più o meno come mostrato di seguito:

public static IExtendedLogger General
{
    get
    {
        AddExtraInformation(general);
        return general;
    }
}


private static void AddExtraInformation(IExtendedLogger logger)
{
    HttpContext ctx = HttpContext.Current;

    if (ctx != null)
    {
        logger.ThreadProperties["Url"] = ctx.Request.Url;
        logger.ThreadProperties["UrlReferrer"] = ctx.Request.UrlReferrer;
        logger.ThreadProperties["UserAgent"] = ctx.Request.UserAgent;
        logger.ThreadProperties["UserHostName"] = ctx.Request.UserHostName;
        logger.ThreadProperties["ServerVariables"] = ServerVariables(ctx.Request.ServerVariables);
        logger.ThreadProperties["Form"] = ServerVariables(ctx.Request.Form);
        logger.ThreadProperties["RawURL"] = ctx.Request.RawUrl;
        logger.ThreadProperties["ServerName"] = ctx.Server.MachineName;
        logger.ThreadProperties["ThreadLanguage"] = Thread.CurrentThread.CurrentCulture.DisplayName;
    }
}

In realtà non c’è nulla di strano, di fatto lo stesso codice in un’altro webserver funzionava alla grande. “Sbingando” (cercando con bing) un po’, ho scoperto di non essere l’unico ad avere questo problema e la motivazione scatenante è dovuta da un insieme di fattori:

  • IIS 7/7.5;
  • Integrated Mode;
  • Accesso all’HttpContext dall’Application_Start del global.asax;

L’unica soluzione che ho trovato (al momento) è quella di cambiare uno di questi fattori, quindi o cambiare la modalità da Integrated a Classic, o evitare di utilizzare l’HttpContext nell’Application_Start.
Personalmente ho scelto la seconda, ritengo che l’integrated mode di II7.x sia una delle features più interessanti (maggiori info qui), o per lo meno è sicuramente più utile dell’HttpContext nell’Application_Start per un semplice log di avvio.

Un’altra possibile soluzione può essere quella di “aspettare” che il metodo Application_Start sia concluso per poi accedere all’HttpContext come spiegato da Mike Volodarsky qui e mostrato dallo snippet seguente:

void Application_BeginRequest(Object source, EventArgs e)
{
    HttpApplication app = (HttpApplication)source;
    HttpContext context = app.Context;
    // Attempt to peform first request initialization
    FirstRequestInitialization.Initialize(context);
}

class FirstRequestInitialization
{
    private static bool s_InitializedAlready = false;
    private static Object s_lock = new Object();
    // Initialize only on the first request
    public static void Initialize(HttpContext context)
    {
        if (s_InitializedAlready)
        {
            return;
        }
        lock (s_lock)
        {
            if (s_InitializedAlready)
            {
                return;
            }
            // Perform first-request initialization here ...
            s_InitializedAlready = true;
        }
    }
}

Ciauz


Comments