Wednesday, February 28, 2007

A C# programmer's first experience wading in Boo

Boo is a .NET static-typed language with a python scripting feel.  It's neat because you have less to type (and maintain) and get much of the same functionality.  SharpDevelop also has lots of built-in support for it, which made trying it out easy.  I decided to try it out when writing a program that would do all the mind-work for me in playing the Clue board game

Here I summarize my experience in bullet form.

Pros:

  1. Easy to pick up and learn as you go (mostly).
  2. Type inference means less code.
  3. Very responsive user base on Google Group.
  4. Great example of good prototyping language that can grow into large projects.
  5. Decent IL is emitted by the compiler.

Cons:

  1. No support for member shadowing (child class redefines a parent's member as a different type or attributes)
  2. I miss some of the compile-time errors I get from common mistakes that the C# compiler gives me.
  3. The compile-time errors the Boo compiler does give are difficult to read to figure out what the root cause was.
  4. Arrays are confusing (for me, but I'm not a python developer).
  5. The debugger in SharpDevelop (at least for Boo projects, I don't know if it's for all languages) does not support watches, or setting the instruction pointer, or attaching to running processes.  It's amazing what the open-source community has done so far, but a lot of work remains to be done.

Summary

Try Boo out and give feedback.  I have to switch to another language for now to get my project finished, but it's a good start for the language.

Tuesday, February 27, 2007

A new .NET OpenID implementation written in C#

Quite a bit of stir has been raised about Janrain's popular .NET implementation of OpenID being written in Boo rather than C#.  Personally, I take my hat off to the folks at Janrain who worked diligently to provide this free, open source OpenID implementation.  To me the language of the library is inconsequential because I reference it as a compiled assembly and the language never affects me.  The spirit of .NET is all about using the best language for the job.  To some others, it seems to affect them more.

A band of .NET developers has begun to port the library to C#.  I might have dismissed the effort as I wished to support the original author of the code with his attempt at Boo, but I recently learned that the Janrain implementation is retiring due to this upstart C# effort.  With that news, I'm throwing my hat in the ring by joining the C# effort.  The project site is on Google Code.  We also have a discussion board on Google Groups.

My immediate plans are to help port the library to C# as needed and build my ASP.NET controls into their library.  We're excited to be working together on this project, and look forward to making a great OpenID library.  We'd like for this library to make it drop-in easy to become an OpenID server (the way my existing controls make being an OpenID consumer).

There has been plenty of talk about InfoCard and OpenID working together to prevent phishing attacks.  I am investigating how to make a library that brings an OpenID server and an InfoCard consumer together for any web site in a drop-in fashion as well.  This InfoCard addition will probably come as a separate library as it won't be mono-compatible (until those folks re-implement .NET 3.0).  I'll keep you informed on this blog.

Thursday, February 01, 2007

Why your NetCF apps fail to call some web services

Here's the scenario: You are writing an NetCF app and trying to call a web service from that app.  You generated the code for the client proxy class using Visual Studio's "Add Web Reference" command.  Code is generated, you call into it, and you run your app.  The call fails with a cryptic error from the web service saying something about a malformed message.  If you try the same thing from a desktop app it works perfectly.  Sound familiar?  Read on for the reason and solution.

I'll address the common cause of xml element mis-ordering here.

Background

Web services and serializers

Calling web services involves serializing objects and sending the resulting xml to the web service, and deserializing the xml response back into objects.  This is usually totally transparent to the developer, who just invokes a method and the magic happens behind the scenes.  The serialized objects come from classes that are usually generated for you by Visual Studio or command-line tools like wsdl.exe or svcutil.exe.  They are constructed based on the service WSDL in such a way that their serialized format matches what the service is expecting, and such that they can be deserialized from the xml the service will respond with.  These classes are called "client proxy classes."

Both the desktop .NET Framework and the .NET Compact Framework use the XmlSerializer class for serializing and deserializing these objects.  When using the WCF stack, the desktop framework will use their recently added DataContractSerializer instead of the XmlSerializer.  Both of these serializers rely on reflection to query the generated client proxy classes and to generate the required xml. 

Reflection

The .NET runtime does not ever care about the order a given type's elements are declared.  For example, the class:

class Fruit {
int seeds;
string color;
}

Is equivalent to

class Fruit {
string color;
int seeds;
}

This makes sense.  Unfortunately though, because of this when you use reflection to query the members of a type, the order of those members is not guaranteed to be in declaration order, or even to be consistent as you switch between versions of the .NET Framework.  In fact, the order in which reflection returns members did in fact change between versions 1.1 and 2.0 of the framework. 

How non-deterministic ordering affects web services

Because the serializers in .NET rely on reflection, they are affected by the non-deterministic ordering of members that reflection provides.  The order of elements serialized will change with whatever order reflection provides members in.

The .NET designers anticipated this problem, and provided a way to force a specific ordering of serialized elements.  The xml serializer attributes that you can decorate your serializable classes with support an Order attribute that you can use to guarantee some desired ordering of elements.  For example, you could force the Fruit class used earlier to put before no matter what order reflection provides by changing the class to read like this:

class Fruit {
[XmlElementAttribute(Order=1)] int seeds;
[XmlElementAttribute(Order=2)] string color;
}

The attributes will retain the Order property's value regardless of reflection order, and that information can be used within the serializer to keep the order to the way the app developer intended.

The problem: why it "works" on desktop's framework and not on NetCF

Although neither desktop nor NetCF's framework guarantees ordering, it so happens that desktop's serializer preserves the order better than NetCF's.  Desktop's serializer isn't perfect either, but it's predictable enough that developers take its order for granted and then wonder why NetCF's serializer doesn't behave the same way. 

Unfortunately, the wsdl.exe and Visual Studio IDE developers were among those developers that seem to have forgotten that ordering is not guaranteed unless explicitly defined, and so neither generate the code in the client proxy classes to set the Order properties necessary to guarantee the correct ordering.  It seems they assumed that declaration order is the default, since the desktop framework (mostly) works that way. 

The wsdl.exe tool does offer an "/order" switch that will set order explicitly, but unfortunately this command line tool generates code that won't compile on NetCF projects because of the limited API exposed by NetCF. 

The workaround

So until the code is fixed in Visual Studio and/or wsdl.exe, you have a couple of options to get your NetCF projects to call these web services that require specific order:

  1. Use wsdl.exe /order to generate your client proxy class, and then remove all the code not supported by NetCF until your project compiles. 
  2. Use Visual Studio to generate your client proxy class, then run wsdl.exe /order in some other directory, and copy just those lines of source code from the resulting class into your project source file that give the explicit ordering.

The ultimate fix

There are a few fixes I'm personally working on to help alleviate this inconvenience for app developers.

  1. I'm trying to get Visual Studio Orcas to include explicit ordering for all generated proxy client classes.
  2. I have changed NetCF's XmlSerializer to preserve declaration order serialization as closely as possible (still not guaranteed).  You'll have to be running on NetCF 2.0 SP2 or later to get this fix. 
  3. The svcutil.exe tool (which deprecates wsdl.exe) automatically generates explicit ordering code where required with no extra steps for the app developer.

Summary

The XmlSerializer cannot guarantee element order either on desktop .NET Framework or the .NET Compact Framework unless the developer gives the order explicitly, although in some cases the "default" ordering will behave as you expect and in some cases it won't. 

The bottom line: where element order is important, use XmlElementAttribute.Order, XmlArrayAttribute.Order, and the other ordering attributes as necessary.