Tuesday, March 31, 2009

A Domain-Driven, DB4O Silverlight RIA

Build a Domain Driven Rich Internet Application using Silverlight, RIA Services and DB4O
I was recently ranting about Silverlight-2 and my annoyance with the WCF layer needed to serialize object instance data to the server. Well Microsoft must have had their mind-reading machines turned up high because the newly announced Mix09 Silverlight 3 & RIA services preview has solved nearly all the problems I was having.

Its the RIA (Rich Internet Application) Services that has the real wow-factor. This is Silverlight finally growing up. Instead of creating Frankenstein client-server apps crudely stitched together with WCF, RIA services allows you to treat your client and server as one, almost seamless application. You share domain design intentions between the client and the server so that your domain acts as you intended regardless of which side of the machine boundary you are on. This is how RIA development was always meant to be. 

You can download all the software kit you need from here the main Silverlight-3 site. I found the best way to get started was to watch the following Mix09 presentations then read the RIA Services Overview.
  • Building Amazing Business Centric Applications with Microsoft Silverlight 3
    "Come hear how simple it is to build end-to-end data-intensive Silverlight applications with the new set of features in Silverlight 3 and .NET RIA Services. Explore Silverlight improvements that help to enable rapid development for business applications and to make your development process more productive"

  • Building Data-Driven Applications in ASP.NET and Silverlight
    "Learn how Microsoft is simplifying the traditional n-tier application pattern by bringing together ASP.NET and Silverlight. Learn about patterns for working with data, implementing reusable and independently testable application logic, and application services that readily scale with growing requirements"
Of course Microsoft just could not help plugging their dystopian Data-Driven-Design vision. Look at the title of that second presentation for goodness sake. 

To counter this and to provide a solid Domain-Driven template for future Silverlight RIA apps I have created an example that does away with the monolithic SqlServer and Igor, the Entity Framework, in favour of an light, fast object database repository that promotes good Code Cohesion, Separation of Concerns and Inversion of Control.

Here is the tech I use in the example:

An Overview of the Domain Driven RIA Example
This example does just enough to highlight the primary functions of RIA services as I see them.
  1. You can define and use your domain objects on the server and then effectively re-use domain logic on the client. 

  2. You can transmit domain objects between the client and server without polluting your domain or requiring an additional DTO transformation layer.
The example is a stripped down version of an app I am currently writing so I have left in all the domain structure even if it is not actually used in the example. This makes the application ready to go if you want to start fleshing it out with your own code.

The functionality is quite simple. You are presented with a Silverlight 3 navigation application. There is a sign-in link that takes you a view containing a username and password field, sign-in and register buttons. 

The code works as you would expect with the additional extra that typing into the Name field triggers a 1 second timer that will check (on the server) that the name is unique. Clicking the Register button creates a new user in the server-side DB40 database. Clicking the Sign In button checks the db for the supplied credentials and, if they exist will return the appropriate User instance and cleverly navigate you back to the home view. 

If you have watched the videos you might at this point think I have cheated and used the built in Authentication Domain Service that come with RIA. Not so. That service relies on having a fat SQLServer file squatting in your solution and that is no good for a Domain-Driven purist. Instead I have implemented a very simple custom identity authentication that could easily be linked up to either Forms or Windows authentication in the usual way.

NB: If you get an error about the URI Prefix then you need to reset the startup application to DomainDrivenRIA.Web and the startup page to DomainDrivenRIA.SilverlightTestPage.aspx

Tuesday, March 17, 2009

Convert dotnet assemblies to Silverlight

The SilverLighter
I have recently been trying to convert an object database (db40 and NeoDatis) for use in a Silverlight application. Along the way I discovered a few interesting things. For example I found that although Visual Studio will not allow you to reference dotnet assemblies from a Silverlight application or class library, this restriction is actually a bit heavy handed. Sometimes it is very useful to use a known Silverlight-safe dotnet assembly, as long as you take responsibility for your own actions.

To enable the re-use of dotnet assemblies in Silverlight I wrote a handy WPF application called  "The Silverlighter". This tool allows you  to convert any dotnet assembly into a Silverlight assembly ready for use in your Silverlight applications or class libraries. 

The knowledge I needed to write The Silverlighter was gleaned primarily from the excellent article by David Betz called Reusing .NET Assemblies in Silverlight. This article clearly explains how the dotnet->Silverlight conversion process works and why it is not a hack. I thought this article was a fascinating insight into the similarities between the dotnet and Silverlight assemblies and is well worth a read.

But before you get carried away (I know I did) and imagine that you are just a click away from re-using your favourite 3rd party assemblies, a word or two of caution. 

Unfortunately just because you can reference an assembly from Silverlight does not mean it will work with Silverlight. If you have read David Betz' article you will know that Silverlight uses a distinct set of System.* assemblies (v These assemblies do not contain all the features of their equivalent dotnet assemblies. For example the following collection types are missing in Silverlight:
  • ArrayList
  • Hashtable
  • SortedList
  • NameValueCollection
Instead Silverlight only allows generic collections to be used, which is a good thing unless your referenced ex-dotnet assembly happens to use one or more of the missing types, in which case your code will blow up with an error similar to "cannot load type ArrayList from assembly System"

Replacing these missing collections with the generic equivalents (you can decompile most assembly code using Reflector) is actually quite trivial however more serious problems are lurking. Silverlight is also missing core features such as:
You can see that Silverlight has removed or redesigned features that are security risks. Again that is a good thing, until you try to re-use assemblies that use these features - then boom.

Anyway, The Silverlighter app does some cool IL trickery so if you have dotnet dlls you know are fine and just want to use them in Silverlight without any nonsense from Visual Studio then it might be just the thing you need.

Additional Notes

There are a few options available to help tweak the functionality.

You can choose to convert only selected System assemblies, although it is recommended that you just leave them all selected unless you have a good reason not to.

The "Recursively process dependent assemblies" feature will, when checked, pick out references from the IL to non System assemblies (your own or 3rd party references) and recursively convert these to Silverlight compliant assemblies as well. The entire dependency tree will be processed in this way.

Finally the path to the ILdasm.exe is exposed just in case you have it at a different location on your system. If you don't have ILdasm.exe anywhere you can get by installing .NET Framework 2.0 Software Development Kit (SDK)

If you notice any bugs or want to add new features then please feel free to checkout the source code and make the updates. Just paste the SVN url into your TortoiseSVN repo-browser, check out the source code under subversion and you are off and running. Good luck.

SVN URL = http://subversion.assembla.com/svn/biofractal/trunk/Blog/Silverlighter

Monday, March 16, 2009

Silverlight and Object Databases

Stop Press: Most of the issues below have now been resolved with the release of Silverlight-3 & RIA Services. See the following post for more details - A Domain-Driven, DB4O Silverlight-3 RIA

I recently decided to write myself a quick Silverlight application for a bit of fun. I wanted an app that could grab stock quotes, do a calculation of my current losses and maybe have some nice blue-gel buttons and what-not. A few evenings of light coding pleasure and good break from all that architectural stuff.  Naturally it did not quite work out that way.

I got a wireframe working pretty quickly but that was not good enough. I wanted to serialize my data so I could start to get some fancy Silverlight graphs with bouncy bars. So I found myself grabbing multiple quotes and using the data to instantiate domain objects in the Silverlight client. Now what? I needed to serialize these instances on the web server. So how do I do that?

I had two options

1. Use isolated storage on the client then use Mesh to synch the data. The only problem with this approach is that the last sentence is the total extent of my knowledge. I want a slope not a cliff face.

2. Use a good old database on the server, why not, and since I am about it lets make that an object database so we don't have to concern ourselves with all that old-fashioned NHibernate, ORM tosh (ah - how quickly I become intolerant).

I chose option #2. And right there it started to get annoying. What I really wanted to do was just use my ODB in the Silverlight client code as if I was coding normally. But of course the Silverlight sandbox had lots to say about that.

To get around this you must write a WCF service layer. Call this an API and you will feel much better because that makes it sound quite cool and computery. You need this comfort blanket because you are about to climb into a time machine a go back 10 years to when you were a script kiddie banging out ASP code.

This WCF 'API' service is going to be the only means you have to serialize data and transmit it between the Silverlight client and the web server. The [DataContract] will require [DataMember] methods to cover every possible action, just like writing all those CRUD sprocs for a relational DB. Of course you could break this jumbled, untestable mess into smaller WCF contracts but that is just more fantasy to cover the poor design, like putting prefixes on your sproc names so they group together to simulate a business layer.

No, the real solution is to do away with the WCF data-layer before you even start. Now don't get me wrong, WCF is fine and very useful but I think it is an abuse to use it a domain serialization interface. We just got rid of RDB DALs so why create another DAL for SaaS?

What is needed is grown up client / server relationship. That would be much better. Then, instead of writing a sprawling WCF thunking layer replete with DTO auto-mappers and all that junk paraphanalia, you get a nice generic client-centric solution with code like this:

myODB.Store(myObject) ;

This focuses coding attention away from the boilerplate WCF data transformation layer and back on to the business useful world of the Domain - where it belongs.

By the way, you can use dotnet assemblies in a Silverlight project. It needs a few quick (but legitimate) 'fixes' to the IL to get them past the Visual Studio fascist guards. I am finishing off a tool that automates the IL work for you makes it nice and easy to convert dotnet assemblies into Silverlight reference-ready assemblies. I will post it here soon.

Stop Press: You can now download the IL Tool mentioned above. See the following blog post for more details - Convert dotnet assemblies to Silverlight