1. Silverlight assemblies cannot reference standard .NET assemblies.
You'll notice in Visual Studio that Silverlight has its own project types. These project types also have restrictions as to which framework
assemblies are available to it.
If you are building components to be deployed with a Silverlight application and some other .NET application such as WCF or WPF, I
suggest creating a single folder with both the standard .NET project file and the Silverlight project file stored in it. Then, you can simply
include the .cs files (or other applicable file types) in each project.
I like to append the .Silverlight naming convention to Silverlight projects. Makes it even easier to keep track of your project files. Also,
remember to change the default namespace in your Silverlight project to match that of your standard .NET project. You'll want to use
the same namespaces in both project types.
2. Not all classes, properties, and methods behave the exact same way between Silverlight and WPF.
You will run into situations where the same class file has methods or properties that have different parameter options or behave
differently in a Silverlight application versus a WPF application. It doesn't happen often but will occur. I've seen it occur with the
BitMapImage class and some conversion methods regarding UTF encoding.
By using the two projects in one folder option mentioned in #1, you can usually get around this by creating a folder for Silverlight specific
class file workarounds. This permits you to include your normal class file in a normal .NET project and the Silverlight workaround file in
your Silverlight project. If you use the same namespace and class names, the rest of the application will never know the difference. Of
course, this technique should be used as a last resort.
3. The System.Data assembly is not available for use in Silverlight.
The Entity Framework 1.0 requires some of your classes to be decorated with attributes that exist in the System.Data
namespace. This virtually excludes using the Entity Framework with Silverlight applications if you intend to use the
exact same class in WCF that you do in your Silverlight application.
4. XAML in WPF does not necessarily equate to XAML in Silverlight.
If you are writing an online version of your application in Silverlight and an offline version in WPF, write your Silverlight
application first. Most of the time, any XAML written in Silverlight will work in WPF.
5. Today's Silverlight application is likely to be tomorrow's offline version in WPF.
It is this statement alone that should give you great pause when attempting to create a religiously pure service
oriented architecture between your Silverlight and WCF application.
If you were to construct an offline version of your application in WPF, many of the design decisions you would make
will likely have different outcomes. There is no longer a network oriented service which forms a natural barrier between
what the client application can use directly and is thus dependent upon the server side to deliver.
Your only real choice is to create shared data contracts with the same namespaces across the WCF, WPF, and
Silverlight applications. Failure to do so will create circular reference and ambiguous namespace issues all over the
place. When this occurs, the only option is to manage different sets of code that perform the same task. Ugh...
I like to make environment aware business logic assemblies which disconnect all logic from classes that could be
transferred to other environments across the WCF, Silverlight, and WPF spectrums.
Then, I prefer to create a shared environment interface to these business logic classes used in the Silverlight and WPF
applications. The WCF application could reference the offline business logic class directly if you chose to bypass the
use of the interface.
This technique enables shared user interface components to use the same business logic interface. The business logic
underneath the interface either uses code for connecting to WCF or code connecting directly to the database in an
offline local database environment.
I tend to keep a separate user interface logic assembly from my WPF and Silverlight projects. This enables a single
code set to manage user interface logic that can be reused in both environments. What we are left with is just the
XAML and top level events in the WPF and Silverlight user interface assemblies. Towards the end of the application
development cycle, you will likely be able to move some of your XAML files into the shared user interface logic
assembly to avoid code duplication.
The process flow ends up looking like this:
Business Logic Interface
WPF Business Logic Silverlight Business Logic
WPF DataBase WCF
WPF Business Logic
6. A WCF reference in a Silverlight or WPF application is just a set of generated source code.
The proxy classes created are not biblical written text creations or laws governing SOA. They are just
code automatically spit out for you.
The Visual Studio service reference creator now offers advanced options which include collection types and
namespace reuse between your WCF, Silverlight, and WPF assemblies in the software family. When creating
online and offline versions of the same application, use this feature. It is a godsend.
* Nhibernate does not yet support ObservableCollection. Beware of this when deciding which collection type to standardize on.
7. Silverlight requires an asynchronous programming model.
You may not like it but you need to accept it. I'll spare you the details you can read elsewhere about Silverlight's
use of the browser network stack. What is important for you to consider is the impact this has on your offline WPF
application. If you are smart, you'll wire up your offline business logic to handle both asynchronous and synchronous
methods. Then, just expose the asynchronous methods via your business logic interface. This avoids confusion by
your user interface developers working in Silverlight and WPF but still permits your WCF layer to reuse the WPF
business logic class and call the synchronous methods.
One additional suggestion (and admittedly an odd one). For insert/update/delete oriented web methods, I've found it
quite beneficial to make the passed in class also the return value (ex. public Customer DeleteCustomer(Customer record)).
The asynchronous nature of Silverlight calls to WCF means you've lost the reference to the record you were working
with when the asynchronous complete event fires. By returning the class you sent in, that same class reference ends
up in the .Result property. You could then use properties on your class to populate status messages or fire some other
method with it as a parameter.
8. Silverlight does not support WCF FaultExceptions.
You'll need to send in a custom exception object as an out parameter to all of your WCF web methods/entry points.
Populate it accordingly in the WCF method and it will show itself in the Silverlight in the MethodCompleted oriented
event from the asynchronous call to WCF. It appears as a property on the result class passed into the event.
I tend to put success or failure properties on the custom exception class to provide a standard way to react to
failures when the asynchronous complete event fires.
You will also need to standardize on methods for passing custom exceptions back up through the user interface
layer in WPF and Silverlight. Remember, Silverlight is reacting to return values from WCF and WPF is most often
times reacting to direct database calls. Any shared user interface components will expect the same behavior of events
from both business logic types.
9. WCF does not permit the DataContract or DataMember attributes on .NET interfaces.
Returning ICustomer instead of Customer from a WCF method results in the use of object instead of a
strongly typed Customer class. You may want to consider using an abstract pattern with Customer if you
want to create other variations of a Customer interface.
10. I was correct.
Building online/offline versions of line of business applications in Silverlight and WPF is a complicated task.
However, it is doable if you think very carefully about component reuse and reduction of code duplication up front.
You will also need to think outside the box and perhaps vary from some of your normal design techniques. It
doesn't make your old design techniques wrong. It just may mean that they are not a good fit for this type of
application and could create obstacles you cannot overcome.