WCF, Arrays and the ExecutionEngineException

This is an anti-recipe for the ExecutionEngineException.  By an anti-recipe, I mean I will demonstrate how to get a certain result that you never want to get, with the expectation that it will help you steer clear of it.

ExecutionEngineException messages are a bit scary. They happen at a pretty low level, first of all, and aren’t easy to debug.  Second, the exception remarks provided on MSDN are:

“Execution engine errors are fatal errors that should never occur. Such errors occur mainly when the execution engine has been corrupted or data is missing.”

I want to point out one scenario which might provoke your code to throw this exception on the principle that forewarned is forearmed.  More importantly, don’t freak out if you run into this – there are some easy workarounds.

When writing a service contract for a WCF web service, you may want to use a IEnumerable<T> as the return type.  Generally this is fine.  If you try to return an array as the underlying type, however, you will get the ExecutionEngineException in .NET 3.5.

This is simply a bug, so you will need to work around it.  You have two choices: either change the signature of your service method or change the underlying type.

If you use the extension method ToList() on your array, everything will work fine.

Alternatively, if you are able to rewrite your service contract, just return the array type rather than trying to use IEnumerable<T>, ICollection<T>, or IList<T>, all of which will cause the same scary exception to be thrown if the underlying type is an array of custom objects (e.g. CustomType[]).

Arrays of simple types (e.g. string[]) do not seem to be a problem.

Arrays of custom objects will generate the exception whether they are the return type on art of the signature of the service method or if they are members of an object returned by the service method. 

I said there are two workarounds, but there are actually three.  This exception seems to only be thrown when you host your service in IIS or Cassini.  If you self-host your service, even using the BasicHttpBinding type, the problem doesn’t show up. 

To reiterate, the problem occurs when a web service contract specifies an IEnumerable<T>, ICollection<T> or IList<T> as the return type and the underlying type returned is actually an array of custom objects.

This has been noted as a bug by Microsoft (https://connect.microsoft.com/wcf/feedback/ViewFeedback.aspx?FeedbackID=433569).  It also appears to be fixed in .NET 4.0.  I have ported my troubled code to VS 2010 Beta 1, and the code works fine.

I don’t think this problem is actually encountered that often for two reasons.  First, we typically don’t use raw arrays that often.  Instead we use generic Lists or even ArrayLists which, even if they are a bit fatter than simple arrays, are awfully convenient.  Second, while it is considered to be a best practice to always return least derived types in methods and properties – in practice this seems to be the exception rather than the rule.

Finally, it doesn’t appear to be a problem with the DataContractSerializer as some have suggested elsewhere.  I can serialize my data contracts just fine when I use the DataContractSerializer on its own.  The problem only seems to happen for me when I try to expose these contracts through a WCF service.  Also, if it were a DataContractSerializer problem, changing to self-hosting shouldn’t help.

Cicero or Kikero?

I’m often curious about how people pronounce their names.

There is a scene from the 1939 version of Goodbye, Mr. Chips in which Robert Donat accedes to the growing trend to pronounce Latin according to scientific rather than poetic principles – Kikero, with a hard ‘c’ rather than a soft one.

The controversy over the conventional pronunciation of Latin is captured in this 1916 article from the New York Times in which a defender of the Italianized pronunciation frames it in terms of Germanic (for it was German philologists who researched and then championed the original pronunciation of Latin) scholarship versus (wer-sus) the pronunciation of the Roman Curia. 

“The Germans, representative of the real and uneffete Romans, have a passion for uniformity and discipline.  Why should two sounds of c be uttered in concillium?  The Latin consonants must march goosestep.  What has made France, England, Italy, decadent and degenerate?  Soften the sound of your c’s and g’s, and you soften the character of the people so abasing them.”

Sometimes, of course, people really don’t care how their names are pronounced.  In exceptional instances, however, there is always a chance that one risks giving offense – Fran-ken-STEEN, as Gene Wilder insisted, not Fran-ken-STAHYN.

As an opportunity to have dinner with Tim Heuer of the Microsoft Silverlight Team approached this week, the correct pronunciation of his name became a small source of anxiety.

When a colleague asked me about it, I suggested that it was pronounced like howitzer without the itz.

Immediately afterwards, I became concerned that it actually was pronounced in the German fashion, HOY-er.

It turned out that both are incorrect.  After consulting with a Microsoft Evangelist, Glen GOHR-dun,  I discovered that Tim’s name is pronounced HYEW-er.

Shawn Wildermuth called me out over the weekend for pronouncing Rocky Lhotka’s name with a long O rather than a short one.  Again the anxiety of pronunciation struck.  Rocky’s last name is actually pronounced LAHT-ka, like the character from Taxi.

Shawn’s last name, in turn, is pronounced with a short rather than a long U – as in MOTHER and not like VERMOUTH.  His first name is not Irish, but instead is derived from the Shawnee Indian nation – such strange things we discuss in the backrooms of conferences.

Since some Wintellect consultants were also with me lounging in the speaker’s room during the Silverlight Firestarter, I inquired into the pronunciation of Jeff Prosise’s name.  The I in his last name turns out to be long, while the stress is on the penultimate syllable: PROH-sahys, like precise but more emphatic.

Silverlight Resources

ATL-Silverlight-Firestarter-logo_resized

Today’s Silverlight Firestarter in Atlanta was a remarkable event due in large part to the remarkable audience.  We started off with about 110 attendees, and while some left throughout the day, just as many came in to replace them.  By my session, which was the last presentation of the Firestarter, the audience was still enthusiastic and responsive – really amazing considering they’d been receiving a massive Silverlight brain-dump for the past nine hours from some of the best Silverlight developers and architects in Atlanta.

As promised, I am posting the various websites I discussed during my presentation on the Silverlight Ecosystem – the combination of corporate and community resources that make up Silverlight.

Silverlight Control Suites:

The Silverlight Toolkit: http://silverlight.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=24246

SL Extensions and Silverlight Contrib: http://www.slextensions.net

Telerik: http://www.telerik.com/products/silverlight.aspx

Component Art: http://www.componentart.com/

ComponentOne: http://www.componentone.com/

Infragistics: http://www.infragistics.com/

Cellbi: http://www.cellbi.com/default.aspx

DevExpress: http://www.devexpress.com/

Divelements: http://www.divelements.co.uk/silverlight/

FarPoint: http://lab.fpoint.com/inputsilverlight/

Netika Tech: http://www.netikatech.com/products/toolkit

Intersoft: http://www.intersoftpt.com/

Vectorlight: http://www.vectorlight.net/controls.aspx

Visifire: http://visifire.com/

Xceed: http://xceed.com/Upload_Silverlight_Demo.html

 

Silverlight Book Recommendations:

Pro Silverlight 3 in C# – Matthew MacDonald (Great reference work)

Silverlight 2 in Action – Campbell & Stockton (Excellent beginner’s book)

Foundation Expression Blend 3 with Silverlight – Victor Gaudioso

Foundation Silverlight 3 Animation – Jeff Paries

Data-Driven Services with Silverlight 2 – John Papa

 

Silverlight Tutorials:

Channel 9

http://silverlight.net/learn/tutorials.aspx

 

Silverlight Blogs:

The Silverlight Geek (Jesse Liberty)

method ~ of ~ failed (Tim Heuer)

Brad Abrams

Shawn Wildermuth

Jeff Prosise

85 Turns (Corey Schuman)

Dan Wahlin

Adam Kinney

Charles Petzold

Page Brooks

Rob Zelt

 

Silverlight Forums:

http://silverlight.net/forums/ (You can usually get your SL questions answered within a day, if not within minutes, at the silverlight.net forums)

http://silverlight.net/community/communitygallery.aspx (An excellent place to look for some inspiration)

 

Free Silverlight Code:

http://www.codeplex.com/site/search?projectSearchText=silverlight

 

Silverlight Contests:

http://telerikwatch.com/2009/07/telerik-silverlight-contest-win-500.html (Due September 14th)

http://www.componentart.com/community/competition2009/ (Due September 22nd)

Between posts …

I had every intention of writing the sequel to Reporting Services and WCF, but life has caught up.

I’ve been busy working with Corey Schuman on throwing the Atlanta Silverlight Firestarter Event, for which I also need to finish practicing a short presentation on Silverlight resources. 

Besides that, I’ve also been working with several Atlanta software community people on organizing a Leading Edge Microsoft User Group.  The goal of the group is to cover the CTP drops and Microsoft Research bits that do not normally get covered in the standard user groups.  You can find our website here: www.alemug.net .

So it’s been a busy couple of weeks.  During that time, Philip Munz, Ioan Hudea, Joe Imad and Robert J. Smith have fed my zombie jones with a mathematical model of zombie outbreaks: http://www.mathstat.uottawa.ca/~rsmith/Zombies.pdf

I have every intention of continuing with the WCF article.  After that, I also intend to do a walkthrough of the steps required to build a WPF application using the MVVM pattern – I don’t think there are any breakdown articles on the web about this – followed by posts about MVVM in Silverlight and a comparison of various UI design patterns – MVVM, MVP (PV and SC), MVC.  Finally, I want to post about a dream (a vision?) I had about Martin Fowler in the year 2029.

Reporting Services and WCF

Ingredients: Visual Studio 2008, SSRS 2008, AdventureWorks2008

While stand alone *.rdlc reports allow one to use data objects as a data source, it would be convenient to be able to do the same thing using published reports.  The XML data source indirectly makes this possible by accepting a path to an *.asmx web service as a valid “connection string” value. 

There seems to be some confusion over whether this can be done with WCF Services as well.  The short answer is yes, as long as the WCF service endpoint appears as a typical web service.  In other words, it must use basicHttpBinding as its binding type.  On the client side, consequently, the reporting services data source must use integrated security (Windows Authentication) for its credential type. 

Given these strictures, if you already have web services exposed for your data, it should take little to no effort to consuming those WCF services from a report.  I will walk through some simple examples on how to do this.  Ultimately the complications are derived not from structuring the WCF service methods themselves, but rather in figuring out how to use the Query syntax that comes with reporting services – which basically serves as a declarative style for generating SOAP service calls.  This problem, it should be pointed out, is not peculiar to WCF services, but was already a road block in figuring out how to make reporting services talk to *.asmx web services.

In working through the details of making reporting services consume a WCF Service, I was greatly aided by two sources.  The first is Jesse Ezell’s blog which beautifully summarizes the steps required, although he makes the task seem rather harder than it actually is and almost convinced me to abandon the effort early on.  The second is an MSDN article written by Jonathan Heide that deals with the query syntax for using reporting services with XML data sources.  I highly recommend both.

The following walkthrough will introduce five services and five reports, each progressively more complicated.  All examples are included in the download linked at the top.

1. A Simple Service

The simplest meaningful service for reporting returns data without taking any parameters.  For this example, we will not implement our own message contract, although the next example will demonstrate some advantages to doing so.

The service method in this example returns an enumeration of Employee types.  Below is the Employee Data Contract and the Interface definition for the service method:

namespace MyReportingService
{
    [DataContract]
    public class Employee
    {
        [DataMember]
        public string FirstName { get; set; }
        [DataMember]
        public string MiddleName { get; set; }
        [DataMember]
        public string LastName { get; set; }
        [DataMember]
        public string JobTitle { get; set; }
        [DataMember]
        public string Email { get; set; }
        [DataMember]
        public int EmailPromotion { get; set; }
    }
}
namespace MyReportingService
{
    [ServiceContract]
    public interface IEmployeesService
    {
        [OperationContract]
        IEnumerable<Employee> GetAllEmployeesRPCStyle();
    }
}

In the actual implementation of the service method, I happen to be retrieving records from the AdventureWorks2008 database.  For our purposes, however, we now have everything we need with just the interface and the data contract to hook reporting services up to our WCF service.  Make sure the binding is set to basicHttpBinding as Visual Studio likes to default to wsHttpBinding when one creates a new service.

Make sure the service is running before continuing to the next step.  If the Reports project and the WCF project are in the same solution, the easiest way to do this is to right click on the service project and select Debug|Start new instance.

The first step in setting up a report that consumes a WCF service is to create an XML Data Source in Visual Studio.  When we do so, we will be prompted for the following information.  Be sure to set XML as the Type and enter the URI of the service as the Connection String:

datasource

We also will need to set the Credentials used for your data source.  As far as I know, web service calls through reporting services always requires that Windows Authentication be used, though perhaps a future release of SSRS will allow us to create a data source that talks to a secured service:

credentials

Having done that, we can now use the Report Wizard to create a new report.  On the first screen, set the data source we just created as the Shared Data Source for the report.

SetDataSource

The next screen, the query screen, is where we’ll be spending most of our time from now on.  Select the Query Builder… at the top of the query screen.  Using the query builder will allow us to test our XML query as we go along.  In the Query Builder window, choose Text as the Command type if it isn’t already selected.

The basic syntax for making a service call will include a Query tag with a nested Method, SoapAction, and ElementPath.

<Query>
<Method Name="GetAllEmployeesRPCStyle" Namespace="http://tempuri.org/"/>
<SoapAction>http://tempuri.org/IEmployeesService/GetAllEmployeesRPCStyle</SoapAction>
<ElementPath IgnoreNamespaces="true">*</ElementPath>
</Query>

There are some things worth noticing here. 

  • We are using the default namespace for our service.  If one overrides the default namespace, the custom namespace will need to go into the Method and the SoapAction.
  • The Method Name, for a service method that doesn’t use its own message contract, is just the name of the service method.
  • The SoapAction specifies the full path to the service, which includes the service namespace, the service name (we are using an interface for our *.svc service, so we want the name of the interface rather than the implementing class), and the service method.
  • ElementPath, which is a specialized version of XPath, parses the data returned from the call.  IgnoreNamespaces should be set to true to enable us to be ignorant of some of the specifics of the SOAP message that has been returned by the service.
  • On this first swipe we will use the “*” as a wildcard syntax to return any repeating data that is found in the result.

If we click on the red bang (or hit F5) the query will run and we can immediately see if the query is written correctly.  The query above will return the following data in the Query Builder:

query1

This is basically the data we want returned but it isn’t shaped quite right.  The “xmlns”, “a” and “i” columns are present because the enumeration we want is actually wrapped up in several other elements, each with attributes that show up in the flattened data.  To get rid of these, we need to specify more precisely the data we want in the ElementPath.

The enumeration of Employee types is wrapped in a Result element, which in return is wrapped in a Response element.  By convention, the names of these elements are based on the name of the service method like this: [ServiceMethodName]Response/[ServiceMethodName]Result.

Instead of simply wildcarding it, we can rewrite the ElementPath to fully specify the data we want:

<Query>
<Method Name="GetAllEmployeesRPCStyle" Namespace="http://tempuri.org/"/>
<SoapAction>http://tempuri.org/IEmployeesService/GetAllEmployeesRPCStyle</SoapAction>
<ElementPath IgnoreNamespaces="true">
GetAllEmployeesRPCStyleResponse/GetAllEmployeesRPCStyleResult/Employee
</ElementPath>
</Query>

This query actually still returns the same data in the image above, but it puts in a good position to start shaping the data the way we want.  Squiggly brackets can be appended to any element in our ElementPath in order to specify the attributes we want to be displayed.   In this case, however, we will use empty squiggly brackets to indicate that we do not want any attributes to be returned for our wrapper elements.  The following ElementPath:

<ElementPath IgnoreNamespaces="true">
GetAllEmployeesRPCStyleResponse{}/GetAllEmployeesRPCStyleResult{}/Employee
</ElementPath>

will return us the following shaped result:

query2

This gets us closer to the shape we want.  You may notice, however, that the columns are in the wrong order.  To be more precise, they are in alphabetical order, which may not be exactly what we want.  There are two ways to fix this.  First, in the Data Contract for the Employee type, we can set a particular order for the Employee properties to be rendered in the returned SOAP message.  This is done by using the Order property off of the DataMember attribute of our properties:

 

[DataMember(Order = 0)]
public string FirstName { get; set; }
[DataMember(Order = 1)]
public string MiddleName { get; set; }
[DataMember(Order = 2)]
public string LastName { get; set; }
[DataMember(Order = 3)]
public string JobTitle { get; set; }
[DataMember(Order = 4)]
public string Email { get; set; }
[DataMember(Order = 5)]
public int EmailPromotion { get; set; }

While this is typically a good idea for versioning Data Contracts, there is a simpler way to order the columns using, once again, the squiggly brackets:

<ElementPath IgnoreNamespaces="true">
GetAllEmployeesRPCStyleResponse{}/GetAllEmployeesRPCStyleResult{}/
Employee{FirstName, MiddleName, LastName, JobTitle,Email, EmailPromotion}
</ElementPath>

There is a final thing we will want to do with out ElementPath.  The underlying type for EmailPromotion is actually an Integer.  If we use the ElementPath as it currently stands, however, EmailPromotion will be used as a String (the default type) when it is consumed by the report.  Sometimes this doesn’t matter.  If we wanted to aggregate on EmailPromotion, however, in order to do sum values or average values, we would have to convert the value of EmailPromotion in an expression to make it possible.

Fortunately, we can also specify the type of each Employee column in the ElementPath.  Return types are indicated by placing the Visual Basic type name – Short, Integer, Long, Decimal, Single, Double, Date, String, Boolean, etc – between ellipses after the column name.

I should point out that since we are simply parsing XML using the ElementPath syntax, and since the SOAP message tells us nothing about the underlying types of the data that is returned, the actual property types of the Employee Data Contract are in effect irrelevant as far as reporting services is concerned.  They could all be typed as objects and it would not matter to the design of the report.  The typing occurs in the ElementPath and nowhere else.

The query for our report should now look like this:

<Query>
<Method Name="GetAllEmployeesRPCStyle" Namespace="http://tempuri.org/"/>
<SoapAction>http://tempuri.org/IEmployeesService/GetAllEmployeesRPCStyle</SoapAction>
<ElementPath IgnoreNamespaces="true">
GetAllEmployeesRPCStyleResponse{}/GetAllEmployeesRPCStyleResult{}/
Employee{FirstName, MiddleName, LastName, JobTitle,Email, EmailPromotion(integer)}
</ElementPath>
</Query>

and our data will look like this:

query3

I will continue this series by talking about WCF Message Contracts and how to pass parameters in the next post.