October 2008 Entries
Asp.Net HttpSessionState in Microsoft Unit Tests Framework

We have some unit tests that tests code which relies on a variable stored in the Asp.Net session state (HttpSessionState) accessed from the HttpContext.Current.Session property.

Our unit tests run within the Microsoft Unit Test framework that comes with Visual Studio, but I think that the technique should apply to other frameworks such as NUnit.

Without doing any work HttpContext.Current returns null. It appears quite easy to make set a current HttpContext to contain a session:

HttpContext.Current = new HttpContext(new HttpRequest("", "http://localhost/", ""), new HttpResponse(new System.IO.StringWriter()));

Now HttpContext.Current returns a context, but HttpContext.Current.Session still returns null. You can attach a basic session object with the following line:

System.Web.SessionState.SessionStateUtility.AddHttpSessionStateToContext(
 HttpContext.Current, new HttpSessionStateContainer("",
  new SessionStateItemCollection(),
  new HttpStaticObjectsCollection(), 20000, true,
  HttpCookieMode.UseCookies, SessionStateMode.Off, false));

Now HttpContext.Current.Session can be assigned to and read from allowing my unit tests to run.

I think the code is best put in the a method marked with a [TestInitialize] attribute. The context should also be cleared when a test has completed:

[TestCleanup]
public void Clean()
{
 HttpContext.Current = null;
}

I'm not expecting the HttpContext to work well for any other calls, but it might allow more than just interaction with the session.

Ado.Net Entity Framework with Many to Many Relationships and Eager Load

I've switched a relationship in a model from one to many to many to many and its effecting how the ObjectQuery.Include method is eager loading objects from the database.

An example Module before adding a many to many looks like:

Company -(1..*)-> Cars -(1..*)-> Passengers
Company -(1..*)-> Passengers

A simple query such as:

company = context.Company.Include("Cars").Include("Passengers").First(e => e.CompanyId = companyId);

both populates all the passengers under the company, but also all the passengers under the cars. I.e. company.Cars[0].Passengers is populated.

But when the model is changed to:
  Company -(1..*)-> Cars -(*..*)-> Passengers
  Company -(1..*)-> Passengers

performing the same query doesn't populate the passengers under the cars.

Adding an additional Include("Cars.Passengers") corrects this.

I initially thought this was a bug, but it makes complete sense when you realise that before the entity framework had enough information to construct the graph. It will query all cars and passengers associated with the company, and each passenger row/object references the car it belonged to, therefor it can assign passengers to cars.

With a many to many relationship added there is an additional link table that will not query unless told to. Without the relationship between cars and passengers the framework cannot reconstruct the graph.

Debugging Dot Net Release Configuration Applications

This might be obvious to many people but I've found its not entirely easy to debug a dot net framework executable (i.e. not asp.net) that has been build in its Release configuration. Attaching a debugger to an already running exe build in release mode will not work well as the exe has been optimised.

VS 2005 onwards generated pdb files by default in Release configuration (it's also possible to create them in VS 2003 also) so it is possible to debug these executables, but only if they have been started by a debugger which stops optimisation happening.

I've found the easiest way to do this is to first attach Visual Studio as a debugger to the running exe that you want to debug. Either do this when the application crashes and provides a debug dbox, or whilst it is running eg:

debug exception window

Then choose a new instance of visual studio:

attach vs 2008

Visual studio starts and creates a solution for the executable. At this point the debug session isn't much good as the code is optimised.

The trick is just to stop the debug session and restart it again in visual studio (e.g. pressing ctrl-shift-F5 should achieve this). The application is now started in such as way that optimisation is disabled, VS will load the symbols and allow you to attach the source file when you pause the application or when it encounters an exception.

In addition the solution VS generates can be saved and reloaded so a debug session can be started directly. Much easier than using cordbg.exe.

Asp.Net request thread associated ADO.NET Entity Framework Context

A current project I'm working on is using ADO.NET Entities to enable a web site to collect form based information. One of the first things I've tried to do is associated the ADO.NET Entities ObjectContext with a thread static associated with the current page request.

So far this approach appears to be working well. We define a context factory as follows, all access to the context is now via the factory which creates it on demand and associates it with the current thread.

 public static class ContextFactory
 {
     [ThreadStatic]
     private static ModelContextContainer context;
     private static object staticLock = new object();

     public static ModelContextContainer Context
     {
         get
         {
             // Warning. Adding a watch to the context may change the behaviour
             lock (staticLock)
             {
                 if (context == null)
                     context = new ModelContextContainer();
                 return context;
             }
         }
     }

     public static void Clear()
     {
         lock (staticLock)
         {
             if (context != null)
                 context.Dispose();
             context = null;
         }
     }
 }

In addition a HttpModule is used to dispose the current context when the page request cycle has completed:

Which is configured in the Web.config:

<system.web>
  <httpModules>
    <add name="ContextDispose" type="VisuLive.Studio.Web.ContextHttpModule"/>
  </httpModules>
</system.web>

So far we haven't had any issues following this mechanism, and it allows us to stop creating and disposing context's if more than separate operation on the database is required per page request. 

public class ContextHttpModule : IHttpModule
{
   void IHttpModule.Dispose()
   {
   }

   void IHttpModule.Init(HttpApplication context)
   {
      context.EndRequest += new EventHandler(context_EndRequest);
   }

   void context_EndRequest(object sender, EventArgs e)
   {
      ContextFactory.Clear();
   }
}

XML Serialize ADO.NET Entity Framework Generated Data Object for XSLT

As far as I can tell the MSDN docs don't explicitly show how to generate XML from an entity framework data object, although its very simple.

It appears that as long as you use the DataContractSerializer associated with WCF it all works fine. The example code below shows can be added to any data object partial code.

public XmlDocument SerialiseAsXml()
{
   XmlDocument doc = new XmlDocument();
   using (XmlNodeWriter writer = new XmlNodeWriter(doc, false))
   {
      new DataContractSerializer(this.GetType()).WriteObject(writer, this);
   }
   return doc;
}

Note that XmlNodeWriter is an example bit of code from gotdotnet.com, but it could be replaced with other kinding of writers.

All the data objects are marked with the data contract attribute as follows:

[DataContract(IsReference=true)]

 

The IsReference is quite important in that it means the XML generated works with object graphs with cycles (e.g. a customer has an address property, and the address has a customer property).

More information about is in the MSDN docs, but essentially the first time a data object is serialized an Id attribute is added. The next time the object is serialized an empty node is created with a Ref attribute with the same value as the Id attribute for the XML node containing the objects XML.

One real issue with this mechanism is found when it comes to performing an XSLT transform on the generated XML. You can't totally guarantee where in the XML tree structure the full data objects information can be found as it is dependent on where an object first appears in the object tree. I've come up with a mechanism in the XSLT to perform a lookup when the ref attribute is found which should work in all cases:

  <xsl:template match="do:Customer">
    Customer '<xsl:value-of select="do:Name"/>'

    <!-- decend into the dashboard collection either directly or through a lookuk on the ref -->
    <xsl:for-each select="do:Addresses/do:Address[@z:Id]">
      <xsl:apply-templates select="."></xsl:apply-templates>
    </xsl:for-each>
    <xsl:for-each select="do:Addresses/do:Address[@z:Ref]">
      <xsl:variable name ="ref" select="@z:Ref"/>
      <xsl:apply-templates select="//do:Address[@z:Id = $ref]"></xsl:apply-templates>
    </xsl:for-each>
  </xsl:template>