WCSF 2.0 And IIS7 Integrated Pipeline Mode

While preparing the demos for my session at TechDays Portugal 2008, I’ve noticed that the Web Client Software Factory 2.0 doesn’t work with IIS7 in integrated pipeline mode because it’s trying to access the Request property of the current HTTP Context from the HTTP Application Start “event”, which is not available at this point.


This is an already known issue and you can vote to get it solved.


Meanwhile, there are two ways to work around this:


Changing the Composite Web Application Block


If you are comfortable with having your own build of this block instead of the provided strong named one, you only need to change one statement in the WebConfigModuleInfoStore class (WCSFBlocks-Feb2008\CompositeWeb\Source\CompositeWeb\Services\WebConfigModuleInfoStore.cs, line 105).


Just replace:

configuration =
    WebConfigurationManager.OpenWebConfiguration(context.Request.ApplicationPath + “/” +
                                                 configFilePath.Replace(context.Request.PhysicalApplicationPath, “”));

with:

configuration =
    WebConfigurationManager.OpenWebConfiguration(HttpRuntime.AppDomainAppVirtualPath + “/” +
                                                 configFilePath.Substring(HttpRuntime.AppDomainAppPath.Length));

Changing the application


If you prefer to (or have to) use the provided and strong named version of the Composite Web Application Block, you can always change your application.


Just open the generated global.asax file:

<%@ Application Language=”C#” Inherits=”Microsoft.Practices.CompositeWeb.WebClientApplication” %>

and add:

<script RunAt=”server”>

    private bool initialized;

    protected override void Application_Start(object sender, EventArgs e)
    {
        this.initialized = false;
    }

    protected void Application_BeginRequest(object sender, EventArgs e)
    {
        if (!this.initialized)
        {
            this.initialized = true;

            base.Application_Start(sender, e);
        }
    }

</script>

17 thoughts on “WCSF 2.0 And IIS7 Integrated Pipeline Mode”

  1. On busy sites you may need to worry about multithreading as BeginRequest is not threadsafe.

    private bool initialized = false;
    
       protected override void Application_Start(object sender, EventArgs e)
       {
           // Override the application start so that we can call it at first Application_BeginRequest
    
           // this is necissary for IIS7 Integrated Pipeline because Request is not available in Application_Start
       }
    
       protected void Application_BeginRequest(object sender, EventArgs e)
       {
           if (System.Threading.Interlocked.CompareExchange(ref initialized, true, false))
           {
               base.Application_Start(sender, e);
           }
       }
  2. And if that didn’t work (because bool is not a reference type :( ) try this…

    //0=false 1=true
    
       private int initialized = 0;
    
       protected override void Application_Start(object sender, EventArgs e)
       {
           // Override the application start so that we can call it at first Application_BeginRequest
    
           // this is necissary for IIS7 Integrated Pipeline because Request is not available in Application_Start
       }
    
       protected void Application_BeginRequest(object sender, EventArgs e)
       {
           if (System.Threading.Interlocked.Exchange(ref initialized, 1) == 0)
           {
               base.Application_Start(sender, e);
           }
       }
  3. Thanks Josh.

    Can you provide a link to that information that BeginRequest is not thread safe in integrated pipeline mode? I can’t seem to find it.

  4. Also, method #2 has issues with WebClientAuthorizationModule because when it’s initialized and wants to add handler for AuthorizeRequest – RootContainer is not yet initialized due to moving Application_Start to a later stage.

  5. Hi!
    I’m also having the same problem as Andrey.
    It works most of the time, but sometimes an exception is thrown at the following line:

    base.Application_Start(sender, e);

    See stack trace below:

    System.ArgumentException was unhandled by user code
    Message=”An object with this ID already exists: Shell.”
    Source=”Microsoft.Practices.CompositeWeb”
    StackTrace:
    at Microsoft.Practices.CompositeWeb.Collections.ManagedObjectCollection`1.Build(Type typeToBuild, String idToBuild, Object item)
    at Microsoft.Practices.CompositeWeb.Collections.ManagedObjectCollection`1.AddNew(Type typeToBuild, String id)
    at Microsoft.Practices.CompositeWeb.Collections.ManagedObjectCollection`1.AddNew[TTypeToBuild](String id)
    at Microsoft.Practices.CompositeWeb.Services.ModuleLoaderService.Load(CompositionContainer rootContainer, IModuleInfo[] modulesInfo)
    at Microsoft.Practices.CompositeWeb.WebClientApplication.LoadModules()
    at Microsoft.Practices.CompositeWeb.WebClientApplication.Application_Start(Object sender, EventArgs e)
    at ASP.global_asax.Application_BeginRequest(Object sender, EventArgs e) in c:\temp\WebClient\Global.asax:line 17
    at System.Web.HttpApplication.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
    at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
    InnerException:

    Regards,
    Niklas

  6. I haven’t worked with the Web Client for a long time, but I would say that something is being registerede more than ownce. Looks like too shells are being registered.

    You can:
    1. Get the source from http://webclientguidance.codeplex.com/ and debug into it.
    2. Get the Reflector Pro EAP (http://www.red-gate.com/messageboard/viewforum.php?f=109) and debug into it.
    3. Check the Web Client Guidance forums (http://webclientguidance.codeplex.com/Thread/List.aspx, http://webclientguidance.codeplex.com/WorkItem/List.aspx)

  7. Above solution of putting a check in Application_BeginRequest will not work even with the Interlocked.Exchange check. This is because Application_BeginRequest is called per request and will execute in parallel for simultaneous requests. Assume that two requests arrive at the same time. Request1 will get Interlocked.Exchange to true and enter the if loop to call base.Application_Start. Now, say the context switches to Request2. Request2 will see Interlocked.Exchange as false and not enter the if loop. But it can continue with the request. Now, if Request2 goes ahead before base.Application_Start is called by Request1 then you may get other errors as at that time the WCSF system initialization may not have completed.
    Since Application_BeginRequest is called for every request, putting a check here will slow down the application a bit. Other way is to handle this in Application_Start itself. Since WCSF requires a request object you can create a dummy request object before the base.Application_Start is called.

  8. Hi,
    We are using Feb 2008 version of WCSF. Now, to resolve this, which build you suggest to download?
    My Current Env. VS 2008 SP1, .Net Framework 3.5, IIS 7.0.

    Thanks in advance.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>