Beantown .NET Meeting on 7/10/2008 with Chris Bowen on XNA

Reminder: Beantown .NET is meeting on Thursday, July 10th.

For our July meeting, we have Chris Bowen from Microsoft presenting “Introduction to Game Development with XNA”.

As always, our meeting is open to everyone so bring your friends and co-workers.  If you’re planning to come, please RSVP by 3pm on 7/10.  Click here to RSVP.

Our location (75 State St) has tighter security than our old location so it is important to RSVP in advance to make your security check in as smooth as possible. 

Future meetings:

• No August meeting

• September 4 – TBA

-Ben

Beantown Meeting Details

When: Thursday, July 10, 2008, 6:00 – 8:00pm

Where:

Hollister, Inc.

75 State St., 9th Floor

Boston, MA

http://www.hollisterstaff.com/

617-654-0200


Map:
http://tinyurl.com/23w2a5

Title:

Introduction to Game Development with XNA

Abstract:

Summer is upon us, so what better excuse to break away from the norm and discuss games?  This meeting is for people who enjoy games, and have always wanted to know more about how they’re made… and maybe how to make their own.  XNA (http://creators.xna.com) is a game development platform based on the .NET Framework that helps to make it easy to develop games for Windows, Xbox, and now the Zune as well.  Using the free XNA Game Studio, you can use those same C# skills that pay the bills by day for creating your own games by night (or really whenever you'd like.)  We'll introduce XNA, show you around the XNA world, then create a simple 2D game from scratch to give you a feel for game mechanics and the architecture of XNA.  This session requires no game development experience, only a passion for coding and for games!

Bio:

Chris Bowen (http://blogs.msdn.com/cbowen) is Microsoft’s Developer Evangelist for the Northeast.  A software architect and engineer with over 15 years of experience, Chris joined Microsoft after holding senior architect and developer positions at companies such as Monster, VistaPrint, Staples, and IDX Systems and consulting on web presence and eCommerce projects with others.  He is coauthor of "Professional Visual Studio 2005 Team System" from WROX and “Essential Windows Communication Foundation” from Addison-Wesley.  He specializes in application architecture and building highly-scalable transactional web systems and holds an M.S. in Computer Science and a B.S. in Management Information Systems, both from Worcester Polytechnic Institute.

Some Win32 (unmanaged) C++ noob tips

This weekend I decided to do a little unmanaged C++

My biggest take-away was that I learned that unmanaged (aka Win32) C++ is really, really hard and obtuse.  As a C# guy (who used to be a VB6 programmer), I don't think that I appreciated how easy C# and VB6 are to work with. 

Here are two things that I tried to do that were hard to figure out: Read a single character from the console and read a line from the console.  Reading a single character is helpful for writing a "press any key to continue..." feature.  Reading a line from the console is helpful for -- well -- reading a line of input from the user. 

To read a single character from the console:

  1. Open up your .cpp file
  2. Add the following line somewhere near the top of the file:

    #include "conio.h"
  3. Read the single character with this line:

    int iKeyPress = _getch();

To read a line from the console:

  1. Open up your .cpp file
  2. Add the following lines somewhere near the top of the file:

    #include <iostream>
    #include <string>
  3. Read the line from the console:

    string message;
    getline(cin, message, '\n');

If you want to get really creative, you can even prompt the user for what you want to do by using "printf" to put a message onto the console.

printf("Type in your name then press ENTER: ");
string message;
getline(cin, message, '\n');

 

-Ben

Playing with .NET's Named Pipe Streams (with .NET-to-.NET and Win32-to-.NET samples)

I get my first deadline-free and commitment weekend in weeks and what do I do?  I spend 12 hours writing code.  I didn't leave my house yesterday.  I'm just that cool.  (And yes, it was completely worth it.  I had a great time just writing code.)

Anyway, I decided that I wanted to try to write to a named pipe from unmanaged C++ and read it from .NET.  When I started looking at it, I found that there's a couple of new classes in .NET for working with named pipes: PipeStream, NamedPipeServerStream, and NamedPipeClientStream

Since my C++ skills are virtually non-existent, I decided to try writing a purely .NET version first.  I wanted a Windows Form that would be able to read and write messages in both directions (duplex) via NamedPipeServerStream and NamedPipeClientStream.

Here's a screenshot of the Windows Forms app:

image

In order to be able to read from the PipeStream without blocking the UI thread, I needed to figure out a way to make the Read() logic run in a separate thread.  After working at this for a  bit, it started getting complex enough that I wanted to refactor the PipeStream logic into its own class.  Also, the logic for working with the NamedPipeServerStream was only a little bit different from the NamedPipeClientStream.  After a few refactorings, I ended up with a design that uses a generic PipeStreamWrapperBase<T>.

Here's the class diagram:

image

The "heavy lifting" and the multi-threaded code is all in PipeStreamWrapperBase<T>.  NamedPipeClient and NamedPipeServer extend from PipeStreamWrapperBase<T> and consist mostly of logic to create and initialize either a NamedPipeServerStream or NamedPipeClientStream.

After I got the classes designed, I ran into a tricky problem where calls to Write() and Flush() on the NamedPipeServerStream were hanging.  I could write from the server to the client but not from the client to the server.  It turns out that if either side of the pipe isn't actively waiting to read from the pipe, the writes on the opposite end will block.  This was especially hard to debug because trying to look at the NamedPipeServerStream through the Visual Studio 2008 debugger was causing Visual Studio to hang.  (Yikes!)

Here was my mistake: NamedPipeClientStream has a property called IsMessageComplete.  I was thinking that I'd get notified of a new incoming message by having the IsMessageComplete suddenly go from True to False. 

while (Pipe != null && m_stopRequested == false)
{
    if (Pipe.IsConnected == true && Pipe.IsMessageComplete == false)
    {
        byte[] msg = ReadMessage(Pipe);

        ThrowOnReceivedMessage(msg);
    }
}

Since IsMessageComplete never flipped to false, the code above would NEVER try to read from the pipe.  When I removed that "&& Pipe.IsMessageComplete == false" everything started to work. 

Another problem that I ran in to was not being absolutely clear about what size my input and output buffers were on the PipeStreams.  This was also causing some blocking/hanging behavior.

After I got the .NET client working, the hardest part of getting the unmanaged C++ (Win32) console app going was mostly just figuring out how to convert between the myriad C++ string types and how to read lines from the console.  (Yah...I know...it's pathetic but keep in mind that my only training in C++ was a class in college that I skipped most the time.)

Here's a screenshot of the unmanaged C++ app sending messages to the .NET Form over the pipe.

image

Download the source, Download the binaries

-Ben

Speaking at Beantown .NET User Group on TFS2008 6/12/2008

Reminder: Beantown .NET is meeting this week on Thursday, June 12th.

For our June meeting, I’ll be presenting “Team Foundation Server 2008” as part of the Microsoft Visual Studio 2008 Community Launch Event program (http://tinyurl.com/3uz2c3).

As always, our meeting is open to everyone so bring your friends and co-workers.  If you’re planning to come, please RSVP by 3pm on 6/12.

Our location (75 State St) has tighter security than our old location so it is important to RSVP in advance to make your security check in as smooth as possible. 

Future meetings:

• July 10 – Chris Bowen – XNA Game Studio (http://msdn2.microsoft.com/en-us/library/bb200104.aspx)

-Ben

Beantown Meeting Details

When: Thursday, June 12, 2008, 6:00 – 8:00pm

Where:

Hollister, Inc.
75 State St., 9th Floor
Boston, MA
http://www.hollisterstaff.com/
617-654-0200


Map:
http://tinyurl.com/23w2a5

Title: Team Foundation Server 2008

Abstract:

In this session, Ben will give an overview of Visual Studio Team System with an emphasis on the features and capabilities of Team Foundation Server 2008 including source control, work item tracking, continuous integration builds, and reporting. 

Bio:

Benjamin Day is an independent consultant specializing in the design and development of applications with Visual Studio Team System.  He is a Microsoft MVP for C#, conference speaker, and leads the Beantown.NET User Group.  Ben also provides consulting and training on Visual Studio Team System and Team Foundation Server and is a member of the Visual Studio Team System Customer Advisory Council at Microsoft. When not developing software, Ben plays piano with a Boston-based jazz trio and is an enthusiastic restaurant, food, beer and wine buff. 

Sample Custom Validation and Extraction Rules for Web Tests in Visual Studio Team System 2008

If you haven't seen Web Tests in Visual Studio 2008 Team Suite and Tester Edition (aka. Visual Studio Team System), you really should do yourself a favor and take a look.  They allow you to write and record unit tests that will exercise and validate a running web application or web site. 

The basic idea is that you record a path though an ASP.NET application and the web test recorder records the requests and responses to/from the server.  Once you have the basic recorded test, you can then customize it to send different data to vary your test and also add validation and extraction rules to check that you're getting the response you expect from the application.

The out-of-the-box validation and extraction rules are pretty good but are really just the start of what you'll need to validate your running app.  If you're going to invest time in creating web tests, you'll definitely need rules other than what comes with VSTS.

Here are some of the custom validation and extraction rules that I've written and use regularly:

  • Validate ASP.NET Label Value
  • Extract ASP.NET Label Value
  • Validate ASP.NET GridView Row Count
  • Extract ASP.NET GridView Row Count
  • Text Exists Inside of HTML Tag

Downloads:

To use the rules in your VSTS Web Tests, download the binaries, and add references from your VSTS Unit Test project to both of the DLLs in the zip: HtmlAgilityPack.dll and Com.Benday.WebTesting.WebTestRules.dll.  Once you've added the reference, these rules should show up in the Add Validation Rule and Add Extraction Rule dialogs.

Here's an image of the Add Validation Rule dialog with the custom rules are circled in red.

image

Here's an image of the Add Extraction Rule dialog with the custom rules are circled in red. 

image 

-Ben

 

If you're looking for help installing or configuring Team Foundation Server or want guidance on using and adopting Visual Studio Team System, please contact me via http://www.benday.com.

My slides from DevTeach Toronto 2008

I spoke at DevTeach Toronto 2008 a few weeks ago.  Here are the two talks I gave with links to download my slides.  Enjoy.

Talk #1: Customizing the Team System Web Test Framework (slides)

At first glance, the Web Tests in Visual Studio Team System might not seem very powerful or interesting but the web test framework can actually do a lot – it just takes a little customization.

In this session, Ben will show you how to create custom Validation Rules, Extraction Rules, and Web Test Plugins. Then he’ll show you how to create data-driven Web Tests so that the data sources are under version control along with the test. (It’s harder than you think.) Then finally, Ben will show you how to tie it all together and make it run as part of your Team Build.

Talk #2: Object-Relational Mapping in the Microsoft World (slides)

It’s coming. Some developers have pushed back against it for a long time and called it the domain of hacks and crazy people but it’s coming. Object-Relational Mapping – also known as ORM – has been viewed with passionate skepticism for years but with the LINQ to SQL and Entity Framework, Microsoft has started to publicly endorse this data access technique.

In this talk, Ben will compare three of the major ORM solutions: LINQ to SQL, Entity Framework, and NHibernate. He’ll show their strong and weak points, and discuss how you should incorporate them in your n-tier software architecture. Along the way, Ben will show you how ORMs can help you to manage database schemas and why that actually makes unit testing easier plus demonstrate how to do some basic tasks like row auditing. When we’re done, you’ll have a good handle on ORM in the Microsoft world and hopefully agree that ORM is not just for hacks and crazy people.

My slides from VSLive Orlando 2008

I just finished up doing VSLive Orlando 2008 this week.  To all of you who were in my sessions, thanks for coming.  For those of you who missed the conference, you should go to the next VSLive.

Here are my slides from this year's talks:

If you'd like to try the TFS 2008 report customization that I demo'd, I've blogged a howto here.  I'll be posting my code for the WiX talk sometime over the next few days.

-Ben

Team Foundation Server 2008: Edit the Remaining Work Report to Use Non-Default Status Values

In Team Foundation Server 2005 and Team Foundation Server 2008, one of the best ways to break the out-of-the-box Team Project reports is to add new status values for your work items.  Unfortunately, adding new work item status values is one of the first things that most customers need to do.  For example, I always add an initial status of "Proposed" for my Task and Bug work items in my MSF for Agile Team Projects.  This allows me to add work items to my project without having to decide if I'm actually going to do them. This might seem like a slightly weird idea -- if I don't know if I want to do something then why should I put it in TFS at all? -- but this allows me to "brain dump" into TFS and gives me a place to track all the things I think I MIGHT have to or want to do in the future on my project.  This brain dump frees me up from having to actively remember stuff and lets me worry about actually doing my job rather than trying to be some memorization expert.

This blog post will walk you through the process of modifying the Remaining Work report in an MSF for Agile v4.2 Team Project.  This is a slightly modified version of a lab in my 5-day Visual Studio Team System & Team Foundation Server class.  If you're looking for help installing or configuring Team Foundation Server or want guidance on using and adopting Visual Studio Team System, please contact me via http://www.benday.com.

Pre-requisites:

  • You have already exported the MSF for Agile 4.2 Process Template to your local disk at C:\labs\MSF for Agile Software Development – v4.2.
  • You have installed the Business Intelligence Design Studio (BIDS) 2005 from the SQL Server 2005 installer disk and applied any relevant service packs. Currently, there is no Visual Studio 2008 equivalent of BIDS and therefore this lab requires you to use some Visual Studio 2005 tools.
  • You have customized at least one of the work items in your Team Project to introduce a “Proposed” work item state value (System.State).

The completed version of this lab is available for download from here.

clip_image002

To begin, open up Visual Studio 2005 and create a new project.

clip_image004

- Choose: Report Server Project

- Name: TfsReportCustomization.Reports

- Location: c:\labs\

- Solution Name: TfsReportCustomization

- Click: OK

In Solution Explorer you should now see your new project.

clip_image006

Now, we’ll import the report definition files from the exported MSF for Agile process template.

- In Solution Explorer, right-click the Reports folder | Add… | Existing Item…

clip_image008

- In the Add Existing Item dialog, navigate to:
C:\labs\MSF for Agile Software Development - v4.2\Reports

- Select: All .rdl files

- Click: Add

In the Solution Explorer, you should now see all the files you just added to the project.

clip_image010

The TFS reports reference two Shared Data Sources: TfsReportDS and TfsOlapReportDS. In order to make these reports run in Visual Studio, we’ll need to re-create these data sources.

- In Solution Explorer, right-click the Shared Data Sources folder | Add New Data Source

You should now be on the Shared Data Source dialog.

clip_image012

- Name: TfsReportDS

- Type: Microsoft SQL Server

- Connection string: Data source=TFS2008;initial catalog=TfsWarehouse

NOTE: you should replace “TFS2008” with the name of your Team Foundation Server data tier in the connection string. You may also have to provide the appropriate credentials on the Credentials tab of the Shared Data Source dialog.

- Click: OK

The new TfsReportDS data source should now be visible in the TfsReportCustomization.Reports project as “TfsReportDS.rds”.

clip_image014

Now, let’s repeat this process and create the Shared Data Source for the reporting OLAP connection.

- In Solution Explorer, right-click the Shared Data Sources folder | Add New Data Source

clip_image016

- Name: TfsOlapReportDS

- Type: Microsoft SQL Server Analysis Services

- Connection string: Data source=TFS2008;initial catalog=TfsWarehouse

NOTE: you should replace “TFS2008” with the name of your Team Foundation Server data tier in the connection string. You may also have to provide the appropriate credentials on the Credentials tab of the Shared Data Source dialog.

You should now see the TfsOlapReportDS.rds in the Shared Data Sources folder.

clip_image018

Now let’s begin editing the Remaining Work report.

- In Solution Explorer, double-click “Remaining Work.rdl”

You should now see the Layout tab of the Remaining Work report and the development view of the report. Notice that at the top of the report only the Closed, Resolved, and Active status values are shown.

clip_image020

Best practice: Before you start customizing the report, you should add this project to source control and check in your code. This will give you a baseline version that you can roll back to if you make mistakes.

Ok. Now is when we’ll start adding support for our additional status values. First, we’ll modify the parameters for the dsWorkItemHistory dataset.

clip_image022

- Click the “Data” tab

- Dataset: dsWorkItemHistory

- Click the “…” button

You should now see the Dataset dialog.

clip_image024

- Click the “Parameters” tab

- Add a new parameter to the bottom of the list

o Name: Proposed

o Value: =Parameters!Proposed.Value

- Click: OK

You should now see the dataset query window for dsWorkItemHistory again. Let’s modify the query to pull back the count of Proposed work items.

Locate the following section of the query.

MEMBER [Measures].[Resolved Cumulative Count] AS

Sum(

(StrToMember("[Work Item].[System_State].[System_State].[" + @Resolved + "]")),

[Measures].[Cumulative Count]

)

SELECT

{

[Measures].[Date Value],

[Measures].[Active Cumulative Count],

[Measures].[Closed Cumulative Count],

[Measures].[Resolved Cumulative Count]

} ON COLUMNS,

Now we’ll add the code to bring back the proposed work item count.

MEMBER [Measures].[Resolved Cumulative Count] AS

Sum(

(StrToMember("[Work Item].[System_State].[System_State].[" + @Resolved + "]")),

[Measures].[Cumulative Count]

)

MEMBER [Measures].[Proposed Cumulative Count] AS

Sum(

(StrToMember("[Work Item].[System_State].[System_State].[" + @Proposed + "]")),

[Measures].[Cumulative Count]

)

SELECT

{

[Measures].[Date Value],

[Measures].[Active Cumulative Count],

[Measures].[Closed Cumulative Count],

[Measures].[Resolved Cumulative Count],
[Measures].[Proposed Cumulative Count]

} ON COLUMNS,

- Add the highlighted code as shown above

Now we have to modify the query parameters.

clip_image026

- Click the “Query Parameters” button (circled above)

You should now be on the Query Parameters dialog. We’ll now add the Proposed value to the bottom of the list.

clip_image028

- In the Parameter column, click “<Enter Parameter>”

- In the Parameter column, type: Proposed

- In the Default column, type: Proposed

- Tab off of the newly added row to activate the “OK” button

- Click: OK

The dsWorkItemHistory dataset configuration changes are now complete. In the “Datasets” window (probably in the left pane), you should now see a field named “Proposed_Cumulative_Count”.

clip_image030

- Go to the Datasets pane

- Expand: dsWorkItemHistory

- Verify that “Proposed_Cumulative_Count” is in the list.

If “Proposed_Cumulative_Count” is not in the list, go back and check the “SELECT” portion of the query.

We’ll now start editing the display of the query to use the Proposed count.

clip_image032

- Click on the “Layout” tab

This next part is a little bit tricky. We need to drag the Proposed_Cumulative_Count field from the Datasets window and drop it in a field on the Layout designer that’s hidden until we hover over it. Making this next step work might take a little bit of trial and error.

clip_image034

- In the Datasets window, click and drag the “Proposed_Cumulative_Count” as shown in the diagram above to point #2

- Pause briefly at point #2 to make the data fields list appear

- Continue dragging the Proposed_Cumulative_Count to point #3 and drop it onto the words “Drop data fields here”

If you were successful, you should now see the Proposed Cumulative Count in both the data fields box and in the chart’s legend.

clip_image036

In order to fix the chart’s legend so that it says “Proposed” instead of “Proposed Cumulative Count”, we’ll need to edit the properties for the chart field.

clip_image038

- In the data fields box, right-click: Proposed Cumulative Count | Properties

You should now be on the Edit Chart Value dialog.

clip_image040

- Series label: Proposed

- Click: OK

On the chart layout, you should now see the legend with the value of “Proposed” instead of “Proposed Cumulative Count”.

clip_image042

Only a little bit more to do. We need to make a tiny tweek to one of the report parameters.

clip_image044

- Go to the Properties window for the report

- From the drop-down, choose: Report

- Click: ReportParameters

- Click: “…”

Clicking “…” should have brought up the Report Parameters dialog.

clip_image046

- In the Parameters listbox, choose: Proposed

- Locate the “Internal” checkbox

- Check: Internal

- Click: OK

Now let’s see if we made the edits correctly.

clip_image048

- Click the “Preview” tab

- Set the “ExplicitProject” value to be the name of your team project (example: Agile 2008)

The ExplicitProject field is only visible at development time and is used to say which Team Project you want to query for. During production, this value is retrieved at runtime by looking at the name of the folder that the .rdl file is running from.

- Tab off of the ExplicitProject field.

Moving away from the ExplicitProject field causes the rest of the report execution fields to populate with values. (NOTE: the values you see may not be the same as what is in the image below.)

clip_image050

- Set the start and end date values to a time range that has data

- Click: View Report

You should now see your populated Remaining Work report with values for Proposed work items.

clip_image052

The report customization is finished. If you’re developing under source control, you should check in your changes.

Alright. So we’ve got the report customized. Let’s publish it back to our TFS report server we can actually use it.

- Open Internet Explorer

- Navigate to: http://your_tfs_name/Reports

You should now be on the SQL Server Reporting Services home page and you should see a list of your available Team Project folders.

clip_image054

- Click on the folder for the Team Project you’re customizing. (example: Agile 2008)

Clicking the project link will take you a list of Reports for that project.

clip_image056

- Locate the “Remaining Work” report

- Click: Remaining Work

You’ll now be taken in to the Remaining Work page.

- Click the “Properties” tab

You should now see the Remaining Work report’s properties page.

clip_image058

- Locate the “Update” link

- Click: “Update”

You should now be on the “Import Report” page for Remaining Work.

clip_image060

- Click: Browse…

- Choose the Remaining Work.rdl file on your local disk. If you set up your code as described at the start of this lab, the path should be
C:\labs\TfsReportCustomization\TfsReportCustomization.Reports\Remaining Work.rdl

- Click: OK

You should be on the Properties screen again.

- Click the “View” tab

You should now see your updated Remaining Work report with the Proposed value displayed in the chart.

clip_image062

You’ve completed the customization of the Remaining Work report.

 

If you're looking for help installing or configuring Team Foundation Server or want guidance on using and adopting Visual Studio Team System, please contact me via http://www.benday.com.

"Session state is not available in this context" exception accessing ASP.NET Session in PreRequestHandlerExecute event

I'm doing my final preparations today for speaking at VSLive San Francisco 2008 on Wednesday and Thursday.  I went to check one of my demos and code that used to work started throwing an exception.

System.Web.HttpException was unhandled by user code
  Message="Session state is not available in this context."
  Source="System.Web"
  ErrorCode=-2147467259
  StackTrace:
       at System.Web.HttpApplication.get_Session()
       at UiDesignForTestability.WebUI.Global.InitializeMultiSessionFactoryNHibernate() in C:\code\bendaytfs2\BDC\branches\UiDesignForTestabilityMultiDb\UiDesignForTestability.WebUI\Global.asax.cs:line 24
       at UiDesignForTestability.WebUI.Global.Application_PreRequestHandlerExecute(Object sender, EventArgs e) in C:\code\bendaytfs2\BDC\branches\UiDesignForTestabilityMultiDb\UiDesignForTestability.WebUI\Global.asax.cs:line 45
       at System.Web.HttpApplication.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
       at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
  InnerException:

<ben:Panic operation="Start" intensity="Extreme" />

The offending code was trying to access the ASP.NET Session object from the PreRequestHandlerExecute event in my Global.asax.cs.  This exception shouldn't be possible.  In fact, it should be IMPOSSIBLE because according to the documentation, AquireRequestState should have fired already.  (Can you tell that I was getting anxious?  Getting on a plane tomorrow and the demos aren't working anymore.  I fixed it but I'm still anxious anyway, actually.)

Ok.  Well, it turns out that during Global.asax's processing, it fires all the events for each of the HttpHandlers in the pipeline.  Well, not all HttpHandlers implement IRequiresSessionState.  For example, System.Web.Handlers.AssemblyResourceLoader doesn't and that's what was causing the exception when InitializeMultiSessionFactoryNHibernate() was getting called. 

        protected void Session_Start(object sender, EventArgs e)
        {
            InitializeMultiSessionFactoryNHibernate();
        }

        public void Application_PreRequestHandlerExecute(Object sender, EventArgs e)
        {
            InitializeMultiSessionFactoryNHibernate();            
        }

        private void InitializeMultiSessionFactoryNHibernate()
        {
            if (Session["NHibernateConfiguration"] == null)
            {
                Session["NHibernateConfiguration"] = "UiDesignForTestability";
            }

            SessionFacade.ConfigurationName = Session["NHibernateConfiguration"] as string;
        }

Well, back on 5/30/2006 at 2:33am, Brock Allen wrote the solution into a comment here.  The answer is to check that the current handler implements either IRequiresSessionState or IReadOnlySessionState.

        public void Application_PreRequestHandlerExecute(Object sender, EventArgs e)
        {
            if (Context.Handler is IRequiresSessionState || Context.Handler is IReadOnlySessionState)
            {
                InitializeMultiSessionFactoryNHibernate();           
            }           
        }

Thanks, Brock.  This helped IMMENSELY.

Now the real question is why did that code work before? 

-Ben

Call to IIS-Hosted WCF Service Hangs IIS (well, not exactly)

I ran into this problem a couple of days ago.  I'm working on an n-tier application that uses WCF services hosted in IIS under Vista & Windows 2008.  We've got unit tests to test each tier and they were mostly passing.

We unit test our service code both directly by reference (unhosted) and then unit test them again when they're hosted in IIS.  They worked great when they were unhosted but the hosted ones had intermittent problems.  More and more it looked like IIS was hanging and once the hosted tests started failing, the only way to make them pass again was to restart IIS by running iisreset. 

A weird thing was that all of these unit tests ran just fine on their own.  They only failed when you ran them with other tests but there wasn't any particular test that failed every time.  The tests would run at normal speed and then one of them would just sit there forever and would eventually time out. Once you got the first failure/timeout, all the rest of the tests would fail, too. 

Here's the error:

PeopleManagement.UnitTests.HostedServiceTests.HostedPeopleManagementServiceMembershipSearchFixture.HostedServiceSearchMembershipsByMembershipType threw exception:  System.TimeoutException: The request channel timed out while waiting for a reply after 00:00:59.9990001. Increase the timeout value passed to the call to Request or increase the SendTimeout value on the Binding. The time allotted to this operation may have been a portion of a longer timeout. --->  System.TimeoutException: The HTTP request to 'http://localhost/PeopleManagement.IisServiceHost/PeopleManagementService.svc' has exceeded the allotted timeout of 00:01:00. The time allotted to this operation may have been a portion of a longer timeout. --->  System.Net.WebException: The operation has timed out.

Something about this had the smell of a threading problem. 

I started discussing this problem with my friend and co-worker, Michael Stiefel, and he agreed that this sounded like a threading problem.  Once we were both thinking "threading problem", I started thinking about where there's something multi-threaded in this unit test.  The only multi-threaded part is IIS.  Then like a flash of lightning, I noticed that it didn't matter which tests I ran but HOW MANY I ran.  It was always the 11th test that failed.  Pick any 11 tests -- the first 10 passed and the 11th always failed!

Then another flash of mental lightning and I realized that I'm probably doing something dumb in my code. 

Answer: My team and I were creating instances of the Service Reference proxies to the WCF service but we never called Close() on the proxy.  (Duh.)

Since we're writing services that are only HTTP and since HTTP is stateless, it never occurred to me that I'd have any connection to close.  (Nope.  Not true.)  Michael Stiefel dug up this quote from Michele Bustamante:

Don't forget to close your proxy. If you forget, you will find some interesting results. You will get unexpected behavior and will not know why.

Whew! Ain't that the truth!

-Ben