Blog Home  Home Feed your aggregator (RSS 2.0)  
Web Application Projects vs Web Site Projects - Subtle differences (Part 1) - Manuel Abadia's ASP.NET stuff
 
# Monday, 20 August 2007

Visual Studio 2005 shipped with the Web Site Project to do ASP.NET development. Later, Microsoft realized that the previous mode used in Visual Studio 2003 was also useful, so they added the Web Application Projects later as a download and now it is included in SP1.

The main differences between both approaches are that for Web Application Projects, all code-behind class files and all the stand alone classes for the project are compiled into a single assembly placed in the bin folder; for Web Site Projects, the source code is deployed and when a page is requested dynamic compilation takes place, generating an assembly for each page (this is not 100% true as there are some options to change the default behavior, precompilation, etc, but is enough for the following discussion).

For a more detailed comparison between the two approaches take a look here:

http://msdn2.microsoft.com/en-us/library/aa730880(VS.80).aspx

I'll post a few entries to show some subtle problems I’ve run when working with a Web Site Project and then converting it to a Web Application Project.

The first difference:

I use an HttpModule to handle NHibernate sessions and NHibernate set up. The module captures the Init event and iterates through all loaded assemblies, creating a list of all loaded assemblies and its dependencies, and then initializes NHibernate adding all the assemblies to the Configuration object, so all .hbm.xml mappings embedded in the assemblies are consumed by NHibernate.

The code I was using was:

// gets all executing assemblies

List<Assembly> assemblies = new List<Assembly>(AppDomain.CurrentDomain.GetAssemblies());

 

// adds the dependants to the executing assemblies, filtering system assemblies

AddDependantAssemblies(assemblies);

 

Configuration cfig = new Configuration();

 

// adds the loaded assemblies to the configuration in order to extract all NHibernate mappings

foreach (Assembly assembly in assemblies)

{

    cfig.AddAssembly(assembly);

}

 

// builds the session factory

_sessionFactory = cfig.BuildSessionFactory();

 

/// <summary>Adds the dependant assemblies of a list of assemblies.</summary>

/// <remarks>The list will be modified. Some assemblies can be removed and some will be added.</remarks>

/// <param name="assemblies">The initial assemblies.</param>

public static void AddDependantAssemblies(List<Assembly> assemblies)

{

    // saves the assemblies

    Assembly[] originalAssemblies = new Assembly[assemblies.Count];

    assemblies.CopyTo(originalAssemblies);

 

    assemblies.Clear();

 

    // starts adding the assemblies and its dependants on an empty list

    foreach (Assembly assembly in originalAssemblies) {

        AddDependantAssemblies(assembly, assemblies);

    }

}

 

/// <summary>Adds the dependant assemblies of an assembly.</summary>

/// <param name="baseAssembly">The base assembly.</param>

/// <param name="dependants">A list with the current dependants.</param>

public static void AddDependantAssemblies(Assembly baseAssembly, List<Assembly> dependants)

{

    // adds the assembly as a dependant if it wasn't already in the list

    if (!dependants.Contains(baseAssembly)) {

        // if the assembly doesn't have to be included, exit

        if (FilterAssembly(baseAssembly.FullName)) {

            return;

        }

 

        dependants.Add(baseAssembly);

    }

 

    AssemblyName[] assemblies = baseAssembly.GetReferencedAssemblies();

 

    // iterate through the dependant assemblies adding their dependant assemblies if necessary

    foreach (AssemblyName assembly in assemblies) {

        if (!FilterAssembly(assembly.Name)) {

            AddDependantAssemblies(Assembly.Load(assembly), dependants);

        }

    }

}

 

And this worked fine until I converted the project to a Web Application Project. After the conversion the assembly that had the NHibernate mapping was not loaded in the Init HttpApplication event. It seems that for a Web Site Project all the assemblies that are in the bin folder are loaded when the AppDomain starts, so with AppDomain.CurrentDomain.GetAssemblies() I was able to retrieve the assembly with the mappings. However, for a Web Application Project, only the assemblies that were used until that moment were loaded, and that’s why it failed. The big problem is how to get all assemblies for the web application even if they haven’t been used. 

My first try was to search in the MSDN documentation for the class System.Web.Compilation.BuildManager, as it had something similar for types (the GetType method). Unfortunately the documentation didn’t show any related method (at least in the local Spanish documentation I installed, I haven’t checked others). I googled for a solution to my problem but I didn’t find it anywhere. My only chance was Reflector, so I spend quite some time investigating when I found out the GetReferencedAssemblies public method in the BuildManager class (a class that I have previously discarded because it wasn’t shown in the documentation!). It was very frustrating to waste time for a missing method in the documentation, but using that method solved my problem and works for Web Application Projects and Web Site Projects. The method return an ICollection (to be more precise, an instance of the internal class System.Web.Util.AssemblySet) with the referenced assemblies.

The working code is this:

// gets all referenced assemblies from the ASP.NET application

ICollection referencedAssemblies = BuildManager.GetReferencedAssemblies();

List<Assembly> assemblies = new List<Assembly>();

 

foreach (Assembly assembly in referencedAssemblies) {

    assemblies.Add(assembly);

}

 

// adds the dependants to the executing assemblies, filtering system assemblies

AddDependantAssemblies(assemblies);

 

Configuration cfig = new Configuration();

 

// adds the loaded assemblies to the configuration in order to extract all NHibernate mappings

foreach (Assembly assembly in assemblies) {

    cfig.AddAssembly(assembly);

}

 

// builds the session factory

_sessionFactory = cfig.BuildSessionFactory();

Monday, 20 August 2007 02:02:17 (Romance Daylight Time, UTC+02:00)  #    Comments [0]   ASP.NET  | 
Copyright © 2018 Manuel Abadia. All rights reserved.
DasBlog 'Portal' theme by Johnny Hughes.