Just a quick reminder that the official 3 day CSLA .NET training roadshow continues through the summer. You can still attend in one of these cities:

Orlando

Chicago

Washington, DC

Dallas

The feedback from the classes so far has been excellent! I sat in on part of the class last week in Minneapolis, and I can see why. Miguel is a very good teacher, and his hands-on, continual lab style is a refreshing change from traditional powerpoint-heavy training.

A CSLA .NET user, Aaron Nottestad, has been helping test 3.0 and ran into some issues when using the new WPF CslaDataProvider with editable objects. Thanks Aaron!

As a result, I had to do some work with CslaDataProvider, so it can manage the object’s entire lifetime from create/fetch through to save/cancel. If it can’t manage the lifetime, especially the save, then it can’t get the new object that comes back as a result of save. And if it doesn’t get that new object, then neither does data binding, so the UI controls end up editing an old instance of the object.

So the CslaDataProvider now has Save() and Cancel() methods that you can call to trigger saving or canceling of the business object. Also, as the object is created/fetched CslaDataProvider automatically calls BeginEdit() on the object.

This behavior is all optional, and is controlled by the ManageObjectLifetime property of the CslaDataProvider control. So if you want this behavior, you have to set that property to True. If you leave it at False (the default), then you must manage everything through code – though honestly you can’t manage editable objects through code while using CslaDataProvider. So maybe I should make the default be True? Hmm.

Anyway, this was easy enough to do and worked great. The resulting forms had exactly 4 lines of code – 2 to call Save() and 2 to call Cancel(). It occurred to me that there must be a way to avoid writing those 4 lines of boring code, and Aaron put me onto the RoutedCommand concept in XAML.

A RoutedCommand allows a control like a button or menu item to invoke a method on another control – purely through XAML. There are many examples out there about how this works to create standard Copy/Paste menu items that run against the current TextBox control, and that sort of thing. But none that I found which routed a command to a data provider control.

The reason turns out to be that the target of a command must be a UIElement, and data providers don’t inherit from that base class. Oops…

I thought I was stuck, because I really do want to route the command to CslaDataProvider in this case. However, I figured out a solution.

CslaDataProvider now has a read-only CommandManager property. This property exposes a “command manager” object which does inherit from UIElement and which does handle the Save and Undo routed commands. When it is created by CslaDataProvider, it is given a reference to the CslaDataProvider control, so it simply delegates all Save commands to the CslaDataProvider.Save() method and all Undo commands to CslaDataProvider.Cancel().

With that done, you can route a command from a button or menu item (or any other valid command source) to this CommandManager object, which effectively means you’ve routed the command to the CslaDataProvider control.

The CslaDataProvider gets declared like this:

<csla:CslaDataProvider x:Key="ChildList"

ObjectType="{x:Type this:ChildList}"

FactoryMethod="GetList"

IsAsynchronous="False"

ManageObjectLifetime="True">

</csla:CslaDataProvider>

Then the button controls get declared like this:

<Button

Command="ApplicationCommands.Save"

CommandTarget="{Binding Source={StaticResource ChildList},

Path=CommandManager, BindsDirectlyToSource=True}"

HorizontalAlignment="Left" IsDefault="True">Save</Button>

<Button

Command="ApplicationCommands.Undo"

CommandTarget="{Binding Source={StaticResource ChildList},

Path=CommandManager, BindsDirectlyToSource=True}"

HorizontalAlignment="Left" IsCancel="True">Cancel</Button>

The result is very cool: a form that can edit an object without the need to write any C# or VB code at all. Coupled with the CSLA .NET ValidationPanel to display validation results, you can create a highly interactive data edit form purely with XAML – and of course a CSLA .NET style business object doing all the work behind the scenes.

These new capabilities will appear in CSLA .NET 3.0 Beta 2 - hopefully later this week.

I’ve been spending some quality time with WPF and Visual Studio 2008 Beta 1 (Orcas) over the past few months. A couple observations I’ve made:

Observation ichi:

Putting code in a Page/Window constructor is bad. Yes, I know it is the “C# way”, but it is bad. The “VB way” of putting code in the Loaded event handler is better.

Why?

Because any exceptions thrown in the constructor prevent the page/window from loading at all, and you have to catch those exceptions in the code that is creating the page/window. In many navigation scenarios you can’t catch them, so the user gets an ugly WPF exception dialog.

However, if you do all your init work in the Loaded event handler, the page/window instance already exists. Navigation has already happened, so the “calling code” is no longer responsible for your page/window going haywire. Instead, you can actually handle the exception and show a nice dialog, explaining to the user what happened, and you can (if desired) navigate somewhere else or whatever.

Observation ni:

Handing control events with += or AddHandler is superior to using WithEvents/Handles. Yes, I am a strong advocate of WithEvents/Handles, and it is one of the major missing features in C#, but for WPF it turns out to be a negative.

Why?

Because the Handles clause links the name of the control to the code behind. The AddHandler or += approach, while less attractive in many ways, only couples the event name to the code behind.

The value of the second approach is that any control can route an event to SaveData(). It doesn’t have to be a button, much less Button1. It actually doesn’t even have to be a Click event. It could be almost any event.

The result is that the Presentation (XAML) is less coupled to the UI (VB/C# code) this way than when using Handles.

Unfortunately the Handles approach is more explicit and thus more readable (which is why C# should really get the Handles feature), so we’re left trading readability in order to gain loose coupling…

I posted previously about an issue where the WCF NetDataContractSerializer was unable to serialize a SecurityException object. Microsoft provided some insight.

It turns out that the constructor of the SerializationException object doesn't set the Action property to anything valid. Before you can serialize a SerializationException with NDCS you must explicitly set the Action property to a valid SecurityAction.

This does mean that NDCS is not compatible with the BinaryFormatter in this case, but at least there's a workaround/solution.

I've now updated CSLA .NET 3.0 to explicitly set the Action property any time a SecurityException is thrown, thus allowing the WCF data portal channel to return valid details about the nature of any exception.

The WCF NetDataContractSerializer is an almost, but not quite perfect, replacement for the BinaryFormatter.

The NDCS is very important, because without it WCF could never be viewed as a logical upgrade path for either Remoting or Enterprise Services users. Both Remoting and Enterprise Services use the BinaryFormatter to serialize objects and data for movement across AppDomain, process or network boundaries.

Very clearly, since WCF is the upgrade path for these core technologies, it had to include a serialization technology that was functionally equivalent to the BinaryFormatter, and that is the NDCS. The NDCS is very cool, because it honors both the Serializable model and the DataContract model, and even allows you to mix them within a single object graph.

Unfortunately I have run into a serious issue, where the NDCS is not able to serialize the System.Security.SecurityException type, while the BinaryFormatter has no issue with it.

The issue shows up in CSLA in the data portal, because it is quite possible for the server to throw a SecurityException. You'd like to get that detail back on the client so you can tell the user why the server call failed, but instead you get a "connection unexpectedly closed" exception instead. The reason is that WCF itself blew up when trying to serialize the SecurityException to return it to the client. So rather than getting any meaningful result, the client gets this vague and nearly useless exception instead.

By the way, if you want to see the failure, just run this code:

Dim buffer As New System.IO.MemoryStream Dim formatter As New System.Runtime.Serialization.NetDataContractSerializer Dim ex As New System.Security.SecurityException("a test") formatter.Serialize(buffer, ex)

And if you want to see it not fail run this code:

Dim buffer As New System.IO.MemoryStream Dim formatter As New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter Dim ex As New System.Security.SecurityException("a test") formatter.Serialize(buffer, ex)

I've been doing a lot of work with the NDCS over the past several months. And this is the first time I've encountered a single case where NDCS didn't mirror the behavior of the BinaryFormatter - which is why I do think this is a WCF bug. Now just to get it acknowledged by someone at Microsoft so it can hopefully get fixed in the future...

The immediate issue I face is that I'm not entirely sure how to resolve this issue in the data portal. One (somewhat ugly) solution is to catch all exceptions (which I actually do anyway), and then scan the object graph that is about to be returned to the client to see if there's a SecurityException in the graph. If so perhaps I could manually invoke the BinaryFormatter and just return a byte array. The problem with that is in the case where the object graph is a mix of Serializable and DataContract objects - in which case the BinaryFormatter won't work because it doesn't understand DataContract...

In the end I may just have to leave it be, and people will need to be aware that they can never throw a SecurityException from the server...

Strangeloop is one of the coolest products I've seen (not as cool as Surface, but that's hard to top :) ).

This product is an ASP.NET-aware device that does intelligent caching for web sites. It can do things that seem virtually impossible - it is that cool! Here's Richard Campbell's blog entry with more background.

If you have the need for a nearly transparent boost in performance for your ASP.NET web site, Strangeloop is something you should look at!