Rockford Lhotka

 Tuesday, August 12, 2008

In Part 1 of this series I discussed the overall architecture and structure of a CSLA Light application. In Part 2 I walked through the creation of a simple editable root business object that supports both the 3-tier and 4-tier mobile object models. In Part 3 I discussed the creation of the Silverlight UI.

In this post I will discuss the configuration of the web/app server and the data portal.

All Silverlight applications require a web server, because the Silverlight runtime is hosted in a web page, and the user has to get the web page from a web server (I'm sure there are exceptions to this rule - but in practicality, nearly all Silverlight apps will be downloaded from a web server).

When using CSLA Light in a 3- or 4-tier client/server model, the CSLA Light client application will communicate with a .NET application server. That application server might be the same server from which the Silverlight app was downloaded, or a different server. It might be hosted in ASP.NET or WAS or a custom Windows Service.

The CSLA Light data portal uses WCF as its network transport, and so the only requirement is that the server be reachable from the client using the Silverlight WCF implementation.

CSLA .NET 3.6 includes a special data portal host designed to work with a CSLA Light client. Remember that the CSLA Light data portal is not only going across the network, but it is communicating between the .NET and Silverlight platforms. So while this data portal is functionally similar to the .NET data portal, it has to do some extra work thanks to the cross-platform nature of the scenario.

Configuring the Server

The simplest server configuration is to put the data portal host in the same virtual root as the Silverlight application itself, and that's what I've done in this example.

When the Silverlight application was created, Visual Studio automatically created a host web application project. What I've done is added a WcfPortal.svc file, some web.config entries and a reference to Csla.dll to this project:

image

The WcfPortal.svc file is a typical WCF service file:

<% @ServiceHost Service="Csla.Server.Hosts.Silverlight.WcfPortal" %>

It references the WcfPortal class that contains the data portal host designed to work with CSLA Light. Notice that it comes from the Csla.Server.Hosts.Silverlight namespace.

The web project references Csla.dll, and of course also references Library.dll from the Library.Server project. Remember that Library.Server is a .NET Class Library project containing all the business classes, while Library.Client is a Silverlight Class Library project. Since the web server is running .NET, it needs to reference the .NET assembly.

Finally, the web.config file contains the WCF configuration necessary for the WcfPortal to be available to clients:

<system.serviceModel>
    <behaviors>
        <serviceBehaviors>
            <behavior name="WcfPortalBehavior">
                <serviceMetadata httpGetEnabled="true"/>
                <serviceDebug includeExceptionDetailInFaults="true"/>
            </behavior>
        </serviceBehaviors>
    </behaviors>
    <services>
        <service behaviorConfiguration="WcfPortalBehavior"
                     name="Csla.Server.Hosts.Silverlight.WcfPortal">
            <endpoint address=""
                            binding="basicHttpBinding"
                            contract="Csla.Server.Hosts.Silverlight.IWcfPortal">
                <identity>
                    <dns value="localhost"/>
                </identity>
            </endpoint>
        </service>
    </services>
</system.serviceModel>

This is pretty standard WCF configuration, defining an endpoint for the IWcfPortal interface from Csla.Server.Hosts.Silverlight. Notice that the name of the service (Csla.Server.Hosts.Silverlight.WcfPortal) matches the name of the service specified in the svc file.

At this point the app server is configured and ready to go.

Configuring the Client

In Silverlight, WCF gets its configuration from a file called ServiceReferences.ClientConfig. In Beta 2 I've found that WCF doesn't consistently read this file, but it does work in the sample app I'm discussing here, and I assume Microsoft will fix whatever is causing the file to sometimes be ignored.

The config file looks like this:

<configuration>
    <system.serviceModel>
        <bindings>
            <basicHttpBinding>
                <binding name="BasicHttpBinding_IWcfPortal"
                              maxBufferSize="65536"
                              maxReceivedMessageSize="65536"
                              receiveTimeout="10" sendTimeout="10">
                </binding>
            </basicHttpBinding>
        </bindings>
        <client>
            <endpoint 
                address="http://localhost:1406/SimpleAppWeb/WcfPortal.svc
                binding="basicHttpBinding"
                bindingConfiguration="BasicHttpBinding_IWcfPortal"
                contract="Csla.WcfPortal.IWcfPortal"
                name="BasicHttpBinding_IWcfPortal" />
        </client>
    </system.serviceModel>
</configuration>

Again, pretty standard-looking WCF configuration like you'd probably find in an app.config file. It sets up a client endpoint for IWcfPortal, and provides the URL address to the server.

You can optionally override the configuration in your code by setting two static properties:

Csla.DataPortalClient.WcfProxy.DefaultUrl = "http://localhost/root/WcfPortal.svc"
Csla.DataPortalClient.WcfProxy.DefaultBinding = myBinding

I've been using the config file approach for the most part, but there are certainly scenarios where you might need to switch to different app server addresses in a more dynamic manner.

Finally, your application can specify whether the data portal should run in local or remote mode by setting a property:

Csla.DataPortal.ProxyTypeName = "Csla.DataPortalClient.WcfProxy, Csla"

By default the data portal is configured for remote mode, using WCF, and so the sample app doesn't do any configuration of the ProxyTypeName. But if you did want to run the data portal in local mode, you'd set the ProxyTypeName to "Local":

Csla.DataPortal.ProxyTypeName = "Local"

Then the DataPortal_XYZ methods would run on the Silverlight client and the data portal won't interact with an app server at all. That is particularly useful if you want to directly call remote services from your Silverlight client, and the primary scenario in our design is to support the use of .NET Data Services (code name Astoria) - but that is a topic for another sample app.

In this sample app the only configuration required is in ServiceReferences.ClientConfig. The data portal defaults to the correct settings to use the values in this file to communicate with a CSLA .NET application server.

As you can see, configuring the application server and client to use the CSLA Light data portal is not difficult. The data portal relies on standard WCF configuration on both ends of the network connection, allowing you to exploit the power and flexibility of WCF to access the mobile object capabilities provided by the data portal.

Tuesday, August 12, 2008 9:05:57 AM (Central Standard Time, UTC-06:00)  #    Disclaimer
 Monday, August 11, 2008

There are many code generation tools and templates available for CSLA .NET. You can find a list here

http://www.lhotka.net/cslanet/codegen.aspx

Over time I expect to blog about several of the options, usually as they release new versions or updated templates.

One of the more robust options is CodeBreeze, from Miguel Castro. Miguel just released a new version of his product, which includes completely refreshed CSLA .NET code-gen templates.

Miguel is also the author of the CSLA .NET training class from Dunn training, so he knows CSLA inside and out. He's put up a forum to support CodeBreeze at http://community.steelbluesolutions.com.

Monday, August 11, 2008 3:33:03 PM (Central Standard Time, UTC-06:00)  #    Disclaimer

In Part 1 of this series I discussed the overall architecture and structure of a CSLA Light application. In Part 2 I walked through the creation of a simple editable root business object that supports both the 3-tier and 4-tier mobile object models.

In this post I want to cover the Silverlight UI. Following the theme of this walkthrough, the UI will be very simple so I can illustrate the basic requirements and concepts.

image

At this point in time we're working on UI support for authorization, and I'll discuss it when we have something to show.

UI XAML

The XAML for the UI is not complex, but does have some interesting differences from typical WPF XAML:

<UserControl x:Class="SimpleApp.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml
    xmlns:csla="clr-namespace:Csla.Wpf;assembly=Csla"
    Width="800" Height="600" Loaded="UserControl_Loaded">
  <Grid x:Name="LayoutRoot" Background="Beige">
    <StackPanel Margin="5,5,5,5">
      <StackPanel Orientation="Horizontal" Margin="5,5,5,5">
        <TextBlock Width="100" Text="Id" />
        <TextBox Width="150" Text="{Binding Id, Mode=TwoWay}" />
        <csla:PropertyStatus Property="Name" Source="{Binding}" />
      </StackPanel>
      <StackPanel Orientation="Horizontal" Margin="5,5,5,5">
        <TextBlock Width="100" Text="Name" />
        <TextBox Width="150" Text="{Binding Name, Mode=TwoWay}" />
      </StackPanel>
      <StackPanel Orientation="Horizontal" Margin="5,5,5,5">
        <TextBlock Width="100" Text="Status" />
        <TextBlock Width="150" Text="{Binding Status}" />
      </StackPanel>
      <StackPanel Orientation="Horizontal" Margin="5,5,5,5">
        <Button Width="50" HorizontalAlignment="Left" Margin="5,5,5,5"
              Click="Button_Click" Content="Save" />
        <Button Width="50" HorizontalAlignment="Left" Margin="5,5,5,5"
              Click="Delete_Click" Content="Delete" />
      </StackPanel>
    </StackPanel>
  </Grid>
</UserControl>

The primary difference is that the Mode=TwoWay expression is required to get two-way data binding. In WPF the default is two-way, and in Silverlight it appears to be one-way.

Also, in WPF I would have created a Style for the StackPanel controls to pull the Margin property into a Resources block. While I was able to get a Style working for a TextBlock or TextBox, it would not work for StackPanel. Could be something I did, or a bug or missing feature in Silverlight... Certainly the XAML to do that from WPF doesn't work in Silverlight.

In WPF I probably would have used a CslaDataProvider control as my binding source. The WPF data provider control model is really nice, and I use it all the time. Unfortunately Silverlight doesn't have a data provider concept, and so obviously that's not here.

Notice the PropertyStatus control from CSLA .NET. It is in the Csla.Wpf namespace, but will be moving to Csla.Silverlight. PropertyStatus handles both validation and authorization on a per-control basis, and is responsible for the error icon and tooltip in the UI. It also shows warning and information severity broken rules, and so is more comprehensive than the ErrorProvider in Windows Forms or the error support in WPF.

Creating or Retrieving the Object

When this form is loaded, the business object is either created or retrieved:

Private Sub UserControl_Loaded( _
    ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)

  'Library.CustomerEdit.BeginGetCustomer(123, AddressOf BindCustomer)
  Library.CustomerEdit.BeginNewCustomer( _
     Csla.DataPortal.ProxyModes.Auto, AddressOf BindCustomer)

End Sub

Remember from Part 2 that the BeginNewCustomer() factory creates a new object, while the BeginGetCustomer() retrieves an existing object (or at least mocks that behavior). I've commented out the BeginGetCustomer() call, so the code shown here is creating a new object.

Don't mind the ProxyModes.Auto parameter to BeginNewCustomer(). This is something I'm working on to allow a factory method to force the data portal to run in local mode, and will probably be the topic of a future blog post. The Auto setting indicates that the data portal should use its default behavior.

In either case, the factory methods accept a delegate reference that points to a callback handler. These factories are asynchronous, so the code you see here merely starts the process. You need to implement a callback handler that is invoked when the asynchronous operation is complete. That looks like this:

Private Sub BindCustomer( _
  ByVal sender As Object, ByVal e As Csla.DataPortalResult(Of Library.CustomerEdit))

  Me.LayoutRoot.DataContext = e.Object

End Sub

In C# you could shorten this code by using an anonymous delegate or multi-line lambda instead of creating a totally separate method to handle the callback. Having tried all three approaches, I must say that I still prefer the approach you see here, even in C#, because I find it easier to read the code. Obviously you may find one of the other approaches easier to read - personal preference at work.

The important thing to remember is that BindCustomer() is called by the data portal when the asynchronous operation is complete. In other words, while the object was being created/retrieved on the server, the user was still able to interact with the UI and the browser. Then, when the server is done with its work, this BindCustomer() method is invoked (much like an event being raised) so you can process the result.

The DataPortalResult parameter has a couple important properties: Object and Error. The Object property contains a reference to the business object that was created/retrieved. The Error property contains a reference to any exception that may have occurred during the asynchronous operation.

Please note that the BindCustomer() callback occurs on the UI thread. Behind the scenes the data portal is using WCF, and WCF callbacks in Silverlight always occur on the UI thread. This is really nice, because it means that the developer doesn't have to worry about marshalling the call to the UI thread like they would in WPF.

In the end, all this method does is to take the business object that was just returned from the data portal, and uses it to set the DataContext for the top-level Grid control in the UI. That causes all the detail controls contained in that Grid control to bind to the object according to the binding expressions in the XAML.

Saving the Object

When the Save button is clicked, the object is either inserted or updated into the database. As with CSLA .NET objects, CSLA Light objects keep track of whether they are new or old, and so the UI developer doesn't need to worry about whether the save is an insert or update - that's automatically handled by the data portal.

Also, like in CSLA .NET, the object keeps track of whether it has been changed. So clicking the Save button when the object has not been changed will result in nothing happening - the object automatically detects that it hasn't been changed and doesn't really invoke the server to do a meaningless update operation.

In WPF, with CSLA .NET, the Save button probably would have no code, but would work using the concept of commanding and the CslaDataProvider. Unfortunately commanding doesn't exist in Silverlight, nor do data providers. So in Silverlight the Save button behavior is implemented in old-fashioned code-behind event handlers.

The following code handles the Save button's Click event:

Private Sub Button_Click( _
  ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)

  Dim cust = CType(Me.LayoutRoot.DataContext, Library.CustomerEdit)
  cust.BeginSave(AddressOf BindSaveResult)

End Sub

First, the business object is retrieved from the form's DataContext, and the object is cast into the right type.

Then the BeginSave() method is called to start the save process. Again, all server communication must be asynchronous in Silverlight and so the data portal is asynchronous. This means the save operation is asynchronous as well, and so a callback delegate is passed as a parameter.

Remember that the Click event handler exits immediately and the user can interact with the UI and browser while the save operation is occurring on the server. The UI will probably need to take steps to disable important buttons and controls to prevent the user from interacting with the object (or flooding the server with repeated save requests or something) while the asynchronous operation is executing.

That BindSaveResult() method will be invoked when the asynchronous operation is complete:

Private Sub BindSaveResult( _
  ByVal sender As Object, ByVal e As Csla.Core.SavedEventArgs)

  Me.LayoutRoot.DataContext = e.NewObject

End Sub

Just like in CSLA .NET, the data portal in CSLA Light returns a new object as a result of the save operation. This means that the UI must be rebound to use the new object when the operation is complete.

Deleting the Object

When the Delete button is clicked, the object is deleted from the database. CSLA Light supports both immediate and deferred deletion. In this sample app I'm illustrating deferred deletion, where the object has been retrieved, it is marked for deletion and then saved. Here's the Click handler behind the button:

Private Sub Delete_Click( _
  ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)

  Dim cust = CType(Me.LayoutRoot.DataContext, Library.CustomerEdit)
  cust.Delete()
  cust.BeginSave(AddressOf BindSaveResult)

End Sub

The code is much like that for the Save button, but in this case the Delete() method is called on the object before it is saved. This marks the object to be deleted, so the data portal automatically routes the call to DataPortal_DeleteSelf() so that occurs.

The resulting object (which is now considered a "new" object) is bound to the UI in the same BindSaveResult() method I discussed earlier.

Summary

In this post I have walked through the basic creation of a Silverlight UI that binds to a business object. The object is created or retrieved through the data portal, and then is inserted, updated or deleted through the data portal.

It is probably worth noting that CSLA .NET 3.6 will also include the same asynchronous data portal concepts shown here, and so the same basic code can be written behind a WPF, Windows Forms or even Web Forms UI.

Monday, August 11, 2008 11:50:41 AM (Central Standard Time, UTC-06:00)  #    Disclaimer
 Sunday, August 3, 2008

I've put another prerelease of CSLA Light (CSLA for Silverlight) and CSLA .NET 3.6 online at www.lhotka.net/cslalight/download.aspx.

  1. Check out the new identity base classes in Csla.Security and Csla.Silverlight.Security - they are pretty darn cool!
  2. Check out the new Validator UI control - I think that is really cool!! It won't keep that name, because we're merging the Authorizer functionality directly into that control, so the result will be a consolidated control that does both things - we don't have a name for it yet...
  3. I'm pretty sure the ClientContext and GlobalContext work right, but the unit tests don't show that - so I'd recommend viewing that functionality with suspicion.
  4. I know some of the security tests don't work. Authentication is still evolving and some of the test apps are lagging a bit behind.

Please remember, these are very early preview builds. They are not stable. They are not complete. They may or may not work for you. They are not supported.

We have found, in testing, that Silverlight Beta 2 is not entirely stable. And that WCF in Silverlight is particularly unstable. If you run the unit tests in Silverlight you'll probably find what we find - that they randomly fail sometimes. They'll run. They'll fail. Then they'll run again. With no discernable pattern. Quite frustrating, but I guess this is the nature of working on a beta platform.

I have also put the sample app I've been blogging about at http://www.lhotka.net/files/cslalight/SimpleCslaLightAppvb-080803.zip. This sample app shows all the things I've talked about in my Part 1 and Part 2 posts, and I'll be coming out with more posts in the series in the next few days.

Sunday, August 3, 2008 10:47:53 PM (Central Standard Time, UTC-06:00)  #    Disclaimer

CSLA .NET version 3.5.1 has been released and is now available at www.lhotka.net/cslanet/download.aspx.

This is a bug-fix release, and includes a number of very important bug fixes in the following areas:

  • Windows Forms data binding
  • LINQ to CSLA
  • SmartDate type conversion

Please see the change log for a full list of changes and fixes.

If you are using version 3.5.0, I strongly recommend upgrading to 3.5.1.

Sunday, August 3, 2008 9:49:43 PM (Central Standard Time, UTC-06:00)  #    Disclaimer
 Friday, August 1, 2008

The Twin Cities XNA User Group is hosting a very special event next month...

They're hosting a huge Halo 3 Tournament at Microsoft to raise money for Children's Hospitals and Clinics of Minnesota. They will also have Rock Band 2 and a few standalone machines for people to check out XNA Community Games.

Even if you aren't a gamer, you probably know one. You might even have one in your family. This is an excellent cause worth donating to, and best of all: Magenic is matching funds raised by the event (up to the first $3000)!!

For more information, and to register (or just donate), please visit http://www.charityfragathon.com

Friday, August 1, 2008 1:05:59 PM (Central Standard Time, UTC-06:00)  #    Disclaimer
 Monday, July 28, 2008

In Part 1 I discussed the high level architectural options offered by CSLA Light. In Part 2 I'll start walking through the implementation of the 3-tier mobile object model (which pretty much also covers the 4-tier mobile object model as well).

I'll start with the center of the application: the business layer. As I discussed in Part 1, the business layer spans Silverlight and .NET and defines mobile objects that are capable of moving between the Silverlight client and the .NET web/app server.

(CSLA Light supports both C# and VB - and probably most other languages too - so the fact that this particular demo is in VB shouldn't be taken as an indication that anything only works with VB. Rather, I consciously switch between VB and C# for each demo I write, and it is VB's turn.)

This is intended to be as simple a demo as I can create, and still show something useful. To that end, the demo has exactly one object, with three properties.

Library.Client Setup

The Library.Client project is a Silverlight Class Library. This means it compiles for the Silverlight runtime and can only contain code that will run on the Silverlight client.

It is important to realize that when objects serialize and deserialize, they must have the exact same type name. This includes the assembly name, namespace and type name. The standard .NET way to represent an assembly qualified type name is something like:

"MyNamespace.MyType, MyAssembly"

Since the business objects in Library.Client must be compatible with those in Library.Server, both assemblies must compile to the same assembly name, and must use the same namespaces.

To accomplish this, the project's properties must be changed so the Assembly name and Root namespace do not include the ".Client" part of the name:

image

I've changed them both to "Library", so this will compile to Library.dll and the root namespace is Library.

Library.Server Setup

The same changes to the Assembly name and Root namespace are made to the .NET Class Library project, Library.Server:

image

This project also builds a Library.dll with a root namespace of Library.

If you sign either project, you must sign both projects, and you must use the same key. That way they end up with the same effective assembly name, even though they are on different runtimes.

The end result is that a class in one project is serializable into and out of a class in the other project.

CustomerEdit Class Declaration

The CustomerEdit class exists in both the Library.Client and Library.Server projects, so the code is compiled into both runtimes. This means CustomerEdit can serialize and move between the Silverlight and .NET runtimes.

The class declaration should be pretty familiar to any CSLA .NET developer:

Imports Csla
Imports Csla.Serialization

<Serializable()> _
Public Class CustomerEdit
  Inherits BusinessBase(Of CustomerEdit)

The only odd or new thing here might be the inclusion of the Csla.Serialization namespace. Silverlight has no concept of a Serializable attribute, so CSLA Light supplies one (along with NonSerialized). So in CSLA .NET this namespace exists, but is essentially empty, while in CSLA Light the namespace includes definitions for the attributes "missing" from Silverlight. The end result is that a Serializable class in .NET can compile in Silverlight.

Property Declarations

The property declarations are standard CSLA .NET 3.5 fare:

Private Shared IdProperty As PropertyInfo(Of Integer) = _
  RegisterProperty(New PropertyInfo(Of Integer)("Id"))
''' <Summary>
''' Gets and sets the Id value.
''' </Summary>
Public Property Id() As Integer
  Get
    Return GetProperty(IdProperty)
  End Get
  Set(ByVal value As Integer)
    SetProperty(IdProperty, value)
  End Set
End Property

Private Shared NameProperty As PropertyInfo(Of String) = _
  RegisterProperty(New PropertyInfo(Of String)("Name"))
''' <Summary>
''' Gets and sets the Name value.
''' </Summary>
Public Property Name() As String
  Get
    Return GetProperty(NameProperty)
  End Get
  Set(ByVal value As String)
    SetProperty(NameProperty, value)
  End Set
End Property

Private Shared StatusProperty As PropertyInfo(Of String) = _
  RegisterProperty(New PropertyInfo(Of String)("Status"))
''' <Summary>
''' Gets and sets the Status value.
''' </Summary>
Public Property Status() As String
  Get
    Return GetProperty(StatusProperty)
  End Get
  Set(ByVal value As String)
    SetProperty(StatusProperty, value)
  End Set
End Property

This code compiles in both CSLA Light and CSLA .NET. Notice that I'm using managed backing fields. This allows the CSLA Light serialization to automatically serialize the field values to/from the .NET server.

You can use private backing fields if you choose. If you do use private backing fields, then you'll need to override OnGetState() and OnSetState() and get/set each private field value into the serialization stream. This process is much like the old PropertyBag concept from VB6, and is necessary because Silverlight's support for reflection is insufficient to automate the process.

By using managed backing fields, I avoid having to do that manual work, but I want to be clear that you ultimately get to choose between the two approaches.

Silverlight vs .NET Code

The rest of this post will cover code that is either Silverlight-only or .NET-only. In this sample I've chosen to use compiler directives to separate the code, even though it is all in one file. You can certainly use partial classes instead, and based on this forum thread that might be the preferred approach.

But in this sample, you'll find the following basic structure:

#If Silverlight Then
  ' Silverlight-only code
#Else
  ' .NET-only code
#End If

Compiler directives or partial classes work fine and achieve the same end result.

Silverlight Factory Methods

Now we're at a point where the Silverlight and .NET code may diverge. In Silverlight, any server communication must be asynchronous. This means that the CSLA Light data portal is asynchronous, and thus your factory methods must also be asynchronous.

We've added asynchronous capabilities to the CSLA .NET data portal as well, so you can use this same async factory approach there as well, but typically I don't think that makes a lot of sense.

In any case, the factory methods are designed to be called by the Silverlight UI, and they look like this:

Public Shared Sub BeginNewCustomer( _
    ByVal proxyMode As DataPortal.ProxyModes, _
    ByVal callback As EventHandler(Of DataPortalResult(Of CustomerEdit)))
  Dim dp As New DataPortal(Of CustomerEdit)(proxyMode)
  AddHandler dp.CreateCompleted, callback
  dp.BeginCreate()
End Sub

Public Shared Sub BeginGetCustomer( _
    ByVal id As Integer, _
    ByVal callback As EventHandler(Of DataPortalResult(Of CustomerEdit)))
  Dim dp As New DataPortal(Of CustomerEdit)
  AddHandler dp.FetchCompleted, callback
  dp.BeginFetch(New SingleCriteria(Of CustomerEdit, Integer)(id))
End Sub

In both the create and fetch scenarios the steps are:

  1. Create an instance of the data portal (optionally forcing it to run in local mode)
  2. Add a handler for the async completed event
  3. Call the data portal method to begin the async operation

For this example, I'm requiring that the UI developer pass in the event handler method. In VB this is done with the AddressOf command, and in C# it is a delegate, an anonymous delegate or a multi-line lambda. I'll get to the UI code in a future blog post.

When the data portal is in remote mode, it communicates with a web server running a special CSLA .NET data portal host that is compatible with CSLA Light. I'll get into the server configuration in a later blog post.

The result is that a BeginCreate() or BeginFetch() call results in the data portal using WCF to call the server. When the call gets to the .NET server, it follows much of my discussion in this blog post. A few things have changed in terms of how a factory object is created, but that's a topic for a different sample app.

In this sample app, the client-side data portal calls are routed directly to server-side DataPortal_XYZ methods. These are normal CSLA .NET DataPortal_XYZ methods, and are entirely unaffected by the fact that the client is Silverlight.

Silverlight Constructor

The one other bit of important code in the Silverlight-only area is a Public constructor:

Public Sub New()
  ' required by MobileFormatter
End Sub

The serializer used by CSLA Light is the MobileFormatter, and in Silverlight this serializer requires a Public default constructor on any object it deserializes. This is because Silverlight doesn't allow the use of reflection to create an object with a non-Public constructor like you can in .NET.

This is unfortunate, because a UI developer might accidentally try to use the New keyword to create an instance of the object, like:

Dim cust As New CustomerEdit

While this would compile, it won't really work - not as expected anyway. The UI developer really needs to call one of the factory methods shown earlier to create or retrieve the object successfully. This is why CSLA .NET constructors are typically non-Public, to act as a reminder to the UI developer to use the factory methods. In Silverlight you'll just have to use code reviews to ensure that the UI code is correct.

.NET Constructor

Now let's shift to the .NET-only code. In the .NET-only code there's also a definition of a default constructor, but this one is Private:

Private Sub New()
  ' require use of factory methods
End Sub

This is standard CSLA .NET coding style, using a non-Public constructor to force the UI developer to use the factory methods. In .NET the MobileFormatter does the same thing as the BinaryFormatter or NetDataContractSerializer, and it creates an instance of the object even though it has a non-Public constructor.

.NET DataPortal_XYZ Methods

To keep this sample as easy as possible, the DataPortal_XYZ methods don't actually call a data access layer or talk to a database. They merely set a property on the object to indicate which of the methods was invoked, and where it ran (on Silverlight or on .NET):

Protected Overrides Sub DataPortal_Create()
  LoadProperty(StatusProperty, _
       "Created " & ApplicationContext.ExecutionLocation.ToString)
  MyBase.DataPortal_Create()
End Sub

Private Overloads Sub DataPortal_Fetch( _
        ByVal criteria As SingleCriteria(Of CustomerEdit, Integer))
  LoadProperty(StatusProperty, _
        "Retrieved " & ApplicationContext.ExecutionLocation.ToString)
  LoadProperty(IdProperty, criteria.Value)
  LoadProperty(NameProperty, "Test " & criteria.Value)
End Sub

Protected Overrides Sub DataPortal_Insert()
  LoadProperty(StatusProperty, _
      "Inserted " & ApplicationContext.ExecutionLocation.ToString)
End Sub

Protected Overrides Sub DataPortal_Update()
  LoadProperty(StatusProperty, _
        "Updated " & ApplicationContext.ExecutionLocation.ToString)
End Sub

Protected Overrides Sub DataPortal_DeleteSelf()
  LoadProperty(StatusProperty, _
       "Deleted " & ApplicationContext.ExecutionLocation.ToString)
End Sub

There's nothing special about these methods. You could write this code in CSLA .NET 3.5 for a pure .NET application and it would work just fine. Sure, it is simplistic, in that I'm just loading some hard-coded values into the object's properties, but you should be able to imagine these methods calling your data access layer and getting back a DataReader, DTO, entity object or whatever you are using; and then loading the object's property values from that data source.

Summary

What I hope you take away from this post is that you can take an existing CSLA .NET 3.5 class (that uses managed backing fields), and get it running in CSLA Light too with very little effort. In fact, all you need to do is:

  1. Add an #If Silverlight compiler directive
  2. Put the Silverlight-only factory methods and Public constructor in the Silverlight area
  3. Put your existing .NET-only factory methods and non-Public constructor in the .NET area
  4. Put your existing DataPortal_XYZ methods in the .NET area
  5. Link the file into a Silverlight Class Library

In future posts I'll cover the Silverlight UI and the CSLA Light data portal configuration, including the CSLA .NET data portal server.

Monday, July 28, 2008 5:47:05 PM (Central Standard Time, UTC-06:00)  #    Disclaimer

In preparation for the next public release of CSLA Light (CSLA .NET for Silverlight), I'm going to do a series of posts describing the basic process of creating a CSLA Light application. This first post will provide a high-level overview of the project structure and some concepts.

First, it is important to realize that CSLA Light will support three primary physical architectures: a 3-tier (or SOA) model, a 3-tier mobile objects model and a 4-tier mobile objects model. At all times CSLA Light follows the same n-layer logical architecture of CSLA .NET, where the application has the following layers:

  1. Presentation/UI
  2. Business
  3. Data Access
  4. Data Storage

The primary goal of CSLA Light and CSLA .NET is to support the creation of the Business layer in such a way that the interface points to the Presentation/UI layer and to the Data Access layer are clearly defined.

To a small degree, CSLA Light will assist in the creation of the Presentation/UI layer by providing some custom Silverlight controls that solve common issues and reduce UI code.

Like CSLA .NET, CSLA Light is not an ORM and does not really care how you talk to your database. It simply defines a set of CRUD operators - locations where you should invoke your Data Access layer to retrieve and update data.

3-Tier or SOA Model

If you use CSLA Light in a 3-tier (or SOA) model, your physical tiers are:

  1. Silverlight
  2. Service
  3. Database

You can treat these as tiers, or as separate applications where you use SOA concepts for communication between the applications. That's really up to you. In this case the focus of CSLA Light is entirely on the Silverlight tier. In that Silverlight tier, you'll have the following logical layers:

  1. Presentation/UI
  2. Business
  3. Data Access/Service Facade

To do this, you configure the CSLA Light data portal to run in local mode and it calls the DataPortal_XYZ methods right there in the Silverlight client tier. You implement the DataPortal_XYZ methods to invoke remote services in the Service tier. CSLA Light doesn't care what those services look like or how they are implemented. They could be asmx, WCF, RSS, JSON, RESTful, SOAP-based - it just doesn't matter. If you can call it from Silverlight, you can use it.

The CSLA Light data portal is designed to be asynchronous, because any calls to remote services in Silverlight will be an asynchronous operation. In other words, the data portal is designed to support you as you call these remote services asynchronously.

The only requirement is that by the time your async DataPortal_XYZ method completes, that the object's data be created, retrieved, updated or deleted.

This is the simplest of the CSLA Light architectures (assuming the services and database already exist) because you just create one project, a Silverlight Application, and all your code goes into that project. Or perhaps you create two projects, a Silverlight Application for the UI and a Silverlight Class Library for your business objects, but even that is pretty straightforward.

3-Tier Mobile Objects Model

If you use CSLA Light in a 3-tier mobile objects model, your physical tiers are:

  1. Silverlight
  2. Data portal server
  3. Database

This is more like a traditional CSLA .NET model, because the data portal is used to communicate between the Business layer on the Silverlight tier and the Business layer on the Data portal server tier. Your business objects literally move back and forth between those two tiers - just like they do between the client and server tiers in a CSLA .NET 3-tier model.

One interesting bit of information here though, is that your business objects are not just moving between tiers, but they are moving between platforms. On Silverlight they are CSLA Light objects in the Silverlight runtime, and on the Data portal server they are CSLA .NET objects in the .NET runtime. The CSLA Light data portal makes this possible, and the result is really very cool, because most of your business object code is written one time and yet runs in both locations!

The Data Access layer only exists on the Data portal server, in .NET. So the Silverlight tier relies on the data portal, and the .NET server, for all create, fetch, update and delete behaviors. Also, that data access code is not even deployed to the client.

However, the client does have most business and validation and authorization logic. So the user experience is rich, interactive and immediate - just like a WPF or Windows Forms user experience.

This architecture is a little more complex, and requires that you create several projects. The following figure shows a simple solution with the required projects:

image

Here's an explanation of the projects:

  • SimpleAppWeb: web app hosting the Silverlight xap file and the data portal service
  • Library.Client: Silverlight Class Library containing business classes
  • Library.Server: .NET Class Library containing business classes
  • SimpleApp: Silverlight Application containing the Silverlight UI application

The big thing to notice here, is that the CustomerEdit.vb class exists in both Library.Client and Library.Server. In Library.Server it is a linked file, meaning that the project merely links to the file that exists in Library.Client. You can tell this by the different icon glyph in Solution Explorer.

The reason for this is that CustomerEdit.vb contains code for a business object that moves between the Silverlight client and the .NET server. It contains code that compiles in both environments.

You can then use compiler directives or partial classes to implement code in that class that is Silverlight-only or .NET-only. I started a thread on the forum about which is better - people seem to prefer partial classes, though compiler directives is certainly a clean solution as well.

4-Tier Mobile Objects Model

If you use CSLA Light in a 4-tier mobile objects model, your physical tiers are:

  1. Silverlight
  2. Data portal server (web)
  3. Data portal server (application)
  4. Database

From a Silverlight perspective this is exactly the same as the 3-tier model. The difference is purely in how the CSLA .NET data portal is configured on the web server (#2). In this case, the CSLA .NET data portal is configured to be in remote mode, so all data portal calls on machine 2 are relayed to machine 3.

This is totally normal CSLA .NET behavior, and doesn't change how anything else works. But it can be a useful physical architecture in the case that the web server (#2) that is exposed to the Internet so the Silverlight client can interact with it, is not allowed to talk to the database. In other words, you could have an external firewall between 1 and 2, and then an internal firewall between 2 and 3. So machine 2 is in a DMZ, and machine 3 is the only one allowed to talk to the database.

What I'm describing is a pretty standard web deployment model for CSLA .NET - but with a CSLA Light client out there, instead of a simple web page.

As I continue this series I'll dig into the code of this simple application, showing how to create the business class, configure the data portal and set up the Silverlight UI project.

Monday, July 28, 2008 10:26:08 AM (Central Standard Time, UTC-06:00)  #    Disclaimer
 Sunday, July 27, 2008

I have put CSLA .NET 3.5.1 release candidate 0 online at www.lhotka.net/cslanet/download.aspx.

Version 3.5.1 has some very important bug fixes for 3.5, especially around some of the new property syntax and Windows Forms data binding.

If you are using any of the new 3.5 property syntax, or are using Windows Forms data binding, you really should test 3.5.1 ASAP!

There's only one breaking change in how a "new PropertyInfo(...)" expression is written - I had to remove a constructor. This is unfortunate, but necessary, because the overload was ambiguous with another overload when the property type was string. The compiler will find these for you, and they are easily resolved - just check the change log for info.

Beta 2 was quite stable - no bug reports, only one feature change for data binding - so I expect RC0 to be very good. Please let me know if you encounter issues.

Sunday, July 27, 2008 4:05:08 PM (Central Standard Time, UTC-06:00)  #    Disclaimer
 Friday, July 25, 2008

http://www.msnbc.msn.com/id/25848017/

If you haven't heard the his last lecture, or read the book, you really should. This guy was one of us, a scientist, a thinker, a man of reason. And his speech is incredibly thought provoking and powerful.

The world needs more people like Randy Pausch, and it is sad to think we now have one less.

Friday, July 25, 2008 10:06:43 AM (Central Standard Time, UTC-06:00)  #    Disclaimer
 Monday, July 21, 2008