Rockford Lhotka's Blog

Home | Lhotka.net | CSLA .NET

 Wednesday, August 27, 2008

The second part of the DNR TV show covering CSLA .NET 3.5.1 is now online. Here are links to both parts:

As always, you can download CSLA .NET from here.

Wednesday, August 27, 2008 7:03:12 AM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  | 
 Wednesday, August 20, 2008

I've been thinking a lot about the future of CSLA and of .NET, and I'd like thoughtful input.

The .NET platform is, for lack of a better word, fragmenting. We have .NET, the .NET client-only framework, .NET Compact Framework, Silverlight and probably others. All of these are ".NET", but they are all different.

CSLA will soon support .NET and Silverlight. It sort of supports the Client-Only Framework now, but it was just pointed out to me that while it works, there are compiler warnings in this scenario.

For the past 6 or so years, I've been maintaining all my code twice, once in VB and once in C#. This has never been fun, and wouldn't have been possible at all without help from my colleague Brant Estes and from the Instant VB and Instant C# tools. Even with this, the reality is that I have to do everything twice, and test everything twice.

(yes, I have a unified set of unit tests, but there's a ton of manual testing around data binding in Web Forms, Windows Forms, WPF and now Silverlight that can't be automated)

But now I'm faced with a truly horrific future scenario. CSLA .NET, CSLA Light, possibly CSLA CF and CSLA Client-Only. Four versions of the framework. Two languages for each version. Fixing a single bug requiring changing and testing 8 implementations.

Clearly that's not realistic. Not only would it eliminate any fun, but it just isn't practical. I doubt it would be practical even if I made CSLA a commercial product...

Of course I can cut the complexity in half by maintaining the framework in only one programming language.

This is a touchy thing of course. I was thinking Modula II, but I can't find a good compiler for .NET... :)

Seriously though, the clear choice would be to maintain the framework in C#, at which point I run the risk of alienating the VB community. You might argue I should maintain the framework in VB, but (for better or worse) that would almost certainly alienate a much bigger constituency.

The really important thing is that the framework would support both VB and C#. Regardless of what I do or don't do inside the framework, it can be used by either language (and other languages for that matter) equally well. After all, most of the .NET framework is written in just one language, yet it is used by everyone equally.

Right now CSLA Light is only in C#, though I'm testing in both VB and C# to make sure it supports both equally. I haven't tried, but I imagine you can use it from Ruby or Python too, since both of those languages work in Silverlight too.

Another alternative would be to solicit help from the community. For example, perhaps one or more people would be willing to help keep the VB version of the framework in sync over time. That has its own complications, but might be a worthy solution.

This also ties into my book projects. I'm working on Chapter 16 of 21 for Expert C# 2008 Business Objects right now. As with the previous editions, most of the book is focused on the design and creation of the framework itself, with less focus on how to use the framework.

I think a lot of people would actually prefer a book on how to use the framework, not caring so much how and why I implemented things internally. And I'd enjoy writing that book (in VB and C# editions). But as it is, I'm looking at 2-3 months of work to get CSLA .NET 3.6 working in VB (which will have to wait until the current book is done), then a couple months to get the Expert VB 2008 Business Objects book done. That's 4-5 months where I could write a book on how to use the framework. Or perhaps a series of highly focused ebooks. Or something along that line.

I haven't reached a decision, I'm just thinking long and hard. Thoughtful input is welcome, thanks!

Wednesday, August 20, 2008 3:15:50 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  | 
 Tuesday, August 19, 2008

Magenic a couple fall community events they are involved in organizing and/or sponsoring.

In Chicago there's the Codeapalooza event coming up on September 6. This is sponsored by Magenic and will have speakers from the whole community. It sounds like Justin Chase will be speaking at the event, talking about UnitDriven and the unit testing issues we've been facing while building CSLA Light (Justin is on the CSLA Light dev team).

Then in Minneapolis there's the 5th Twin Cities Code Camp on October 11. I'll be speaking at this event, talking about CSLA Light and CSLA .NET 3.6. By that point CSLA Light should be well into its beta phase and will be a lot of fun to show (and see).

Tuesday, August 19, 2008 1:43:30 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  | 
 Friday, August 15, 2008

One of the features we added in CSLA Light was the idea of a "factory" or "observer" object - kind of like a police sobriety checkpoint - that can be called when any data portal request comes in from the client. This is a server-side object that can examine or manipulate the business object or criteria object sent from the client, before any other server-side processing is allowed.

I liked the idea so much that I decided to put it into the CSLA .NET 3.6 data portal too. Which turned out to be much harder than I expected...

Of course I don't want to break compatibility with the current data portal behavior, so it must continue unchanged.

But if you put the ObjectFactory attribute on your business class, that should redirect the data portal to create an instance of the factory object you specify, and to route all data portal calls to methods on that object instead of calling DataPortal_XYZ as normal.

For example:

[ObjectFactory("Factories.MyFactory,Factories")]
[Serializable]
public class CustomerEdit : BusinessBase<CustomerEdit>

This tells the data portal to not call any DataPortal_XYZ methods, but instead to create an instance of a MyFactory object and to call methods named Create(), Fetch(), Update() and Delete() on that object instead.

This is extensible in numerous ways. You can specify the names of the four methods. You can provide a "factory loader" so that string parameter passed to ObjectFactory can be interpreted differently - how ever you'd like. The default factory loader treats that string like an assembly qualified type name, because I think that's what most people will want.

So you have to create MyFactory:

namespace Factories
{
  public class MyFactory
  {
    [RunLocal]
    public object Create()
    {
      // create object here
      return obj;
    }

    public object Fetch(SingleCriteria<CustomerEdit, int> criteria)
    {
      // retrieve object here
      return obj;
    }

    [Transactional(TransactionTypes.TransactionScope)]
    public object Update(CustomerEdit obj)
    {
      // insert/update/delete object here
    }

    [Transactional(TransactionTypes.TransactionScope)]
    public void Delete(SingleCriteria<CustomerEdit, int> criteria)
    {
      // delete data here
    }
  }
}

Normal method overloading rules apply to these methods. So you can have multiple Fetch() methods with different criteria object types and the data portal will call the right method. This is exactly the same behavior as with DataPortal_Create(), DataPortal_Fetch() and DataPortal_Delete() today.

Notice that the RunLocal and Transactional attributes can be applied to these methods just like they would have been applied to the DataPortal_XYZ methods.

RunLocal is interesting though, because it obviously can only work if you deploy your factory assembly to the client along with the business assembly. In most cases I expect people won't choose to do that, and so won't be able to use RunLocal.

The default for Transactional is to use Manual transactions. In other words, if you don't use the attribute it is entirely up to your factory method to handle any transaction details.

It is very important to realize that when using this factory model, the data portal does virtually nothing for you. It doesn't automatically call MarkOld(), MarkNew() or MarkAsChild(). You assume total responsibility for creating and initializing the business object graph, and for setting the state of all objects in the graph.

Friday, August 15, 2008 2:16:41 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  | 
 Wednesday, August 13, 2008

WPF has this cool concept called a data provider control. CSLA .NET includes a custom data provider control that enables nearly codeless forms (if you don't count XAML as code), by supporting the following functions purely through XAML:

  1. Create/Fetch an object
  2. Save an object
  3. Cancel changes to an object
  4. Add a new item to a list (if the object is a collection)
  5. Remove an item from a list (if the object is a collection)

Silverlight doesn't have a data provider concept, nor does it have commanding. Which means that you need to write code behind the form for all of those actions.

So in CSLA Light we're investigating the possibility of some sort of data provider control to fill in this gap. The idea is that you'd be able to declare a CslaDataProvider as a resource on your form and use it as a data source, and as a handler for the save/cancel/add/remove operations.

This also means we need a way, through XAML, to route things like a button's Click event to methods on CslaDataProvider (because there's no commanding in Silverlight).

At a prototype level what we've got is something like this. The CslaDataProvider goes in the Resources section just like it would in WPF:

<UserControl.Resources>
  <csla:CslaDataProvider x:Key="MyData"
                                     ManageObjectLifetime="True" />
</UserControl.Resources>

Some WPF concepts don't make sense. For example, IsAsynchronous is useless because in Silverlight it will be asynchronous. Others, like IsInitialLoadEnabled might make sense, we're not entirely sure yet.

Your page XAML then uses this as a data source. But where WPF does some magic behind the scenes for data providers, Silverlight doesn't know about data providers. So you have to deal with this yourself when setting the DataContext:

<Grid x:Name="LayoutRoot" DataContext="{Binding Source={StaticResource MyData}, Path=Data}">

The DataContext is set to use the Data property of the data provider, because that's where the actual business object is found. In WPF this indirection is hidden automatically, but in Silverlight you have to do it yourself.

In the Form_Loaded() method in code behind you call your business object's factory method. But rather than handling the async callback yourself, you allow the data provider to handle it:

private void Form_Loaded(...)
{
  var dp = (CslaDataProvider)this.Resources["MyData"];
  CustomerEdit.GetCustomer(123, dp.FetchCompleted);
}

I hope to eliminate even this bit of code behind (at least for parameterless create/fetch scenarios), but the current prototype does require it. The CslaDataProvider exposes a set of async handlers for create and fetch operations.

When the async request completes, the CslaDataProvider object's Data property changes to reflect the new business object. That causes a PropertyChanged event, which in turn causes data binding to refresh the UI so the user sees the data.

That gets us pretty close to the WPF data provider capability of creating or retrieving an object. But the Csla.Wpf.CslaDataProvider goes further, and so the plan is for the Csla.Silverlight.CslaDataProvider to also go further.

The data provider object has methods like Save() and Cancel() that can be called to save the object or cancel changes. The trick then, is how to get UI elements, like a button, to call those methods when Silverlight has no commanding or relative binding.

At the moment we're addressing this with an InvokeMethod object that exposes some attached properties. So you can create a Button like this:

<Button csla:InvokeMethod.Resource="{StaticResource MyData}"
             csla:InvokeMethod.MethodName="Save"
             csla:InvokeMethod.TriggerEvent="Click"
             Content="Save" />

This tells the InvokeMethod object to listen for a Click event from the Button. When it gets a Click event, it invokes the Save() method on the MyData resource. Any RoutedEventHandler or EventHander event can be handled, which should cover nearly all events from any type of UI control. The Button control's Click event, for example, is a RoutedEventHandler, as are most Silverlight control events.

(this is only possible btw, thanks to the relaxed delegate support in the current versions of C# and VB)

The same technique will work to call Cancel(), and presumably AddNewItem() and RemoveItem() at some point (though with RemoveItem() we'll also need a way to pass in a parameter value to specify the item to be removed).

The result is that we're pretty close, at least in concept, to the WPF data provider model, and we avoid the need to write code behind the form for common events like save, cancel, add new and remove.

Wednesday, August 13, 2008 11:03:32 AM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  | 
 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  |  Comments [0]  | 
 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  |  Comments [0]  | 

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  |  Comments [0]  | 
 Sunday, August 03, 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 03, 2008 10:47:53 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  | 

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 03, 2008 9:49:43 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  | 
 Friday, August 01, 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 01, 2008 1:05:59 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  | 
On this page....
Search
Archives
Feed your aggregator (RSS 2.0)
October, 2014 (1)
August, 2014 (2)
July, 2014 (3)
June, 2014 (4)
May, 2014 (2)
April, 2014 (6)
March, 2014 (4)
February, 2014 (4)
January, 2014 (2)
December, 2013 (3)
October, 2013 (3)
August, 2013 (5)
July, 2013 (2)
May, 2013 (3)
April, 2013 (2)
March, 2013 (3)
February, 2013 (7)
January, 2013 (4)
December, 2012 (3)
November, 2012 (3)
October, 2012 (7)
September, 2012 (1)
August, 2012 (4)
July, 2012 (3)
June, 2012 (5)
May, 2012 (4)
April, 2012 (6)
March, 2012 (10)
February, 2012 (2)
January, 2012 (2)
December, 2011 (4)
November, 2011 (6)
October, 2011 (14)
September, 2011 (5)
August, 2011 (3)
June, 2011 (2)
May, 2011 (1)
April, 2011 (3)
March, 2011 (6)
February, 2011 (3)
January, 2011 (6)
December, 2010 (3)
November, 2010 (8)
October, 2010 (6)
September, 2010 (6)
August, 2010 (7)
July, 2010 (8)
June, 2010 (6)
May, 2010 (8)
April, 2010 (13)
March, 2010 (7)
February, 2010 (5)
January, 2010 (9)
December, 2009 (6)
November, 2009 (8)
October, 2009 (11)
September, 2009 (5)
August, 2009 (5)
July, 2009 (10)
June, 2009 (5)
May, 2009 (7)
April, 2009 (7)
March, 2009 (11)
February, 2009 (6)
January, 2009 (9)
December, 2008 (5)
November, 2008 (4)
October, 2008 (7)
September, 2008 (8)
August, 2008 (11)
July, 2008 (11)
June, 2008 (10)
May, 2008 (6)
April, 2008 (8)
March, 2008 (9)
February, 2008 (6)
January, 2008 (6)
December, 2007 (6)
November, 2007 (9)
October, 2007 (7)
September, 2007 (5)
August, 2007 (8)
July, 2007 (6)
June, 2007 (8)
May, 2007 (7)
April, 2007 (9)
March, 2007 (8)
February, 2007 (5)
January, 2007 (9)
December, 2006 (4)
November, 2006 (3)
October, 2006 (4)
September, 2006 (9)
August, 2006 (4)
July, 2006 (9)
June, 2006 (4)
May, 2006 (10)
April, 2006 (4)
March, 2006 (11)
February, 2006 (3)
January, 2006 (13)
December, 2005 (6)
November, 2005 (7)
October, 2005 (4)
September, 2005 (9)
August, 2005 (6)
July, 2005 (7)
June, 2005 (5)
May, 2005 (4)
April, 2005 (7)
March, 2005 (16)
February, 2005 (17)
January, 2005 (17)
December, 2004 (13)
November, 2004 (7)
October, 2004 (14)
September, 2004 (11)
August, 2004 (7)
July, 2004 (3)
June, 2004 (6)
May, 2004 (3)
April, 2004 (2)
March, 2004 (1)
February, 2004 (5)
Categories
About

Powered by: newtelligence dasBlog 2.0.7226.0

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

© Copyright 2014, Marimer LLC

Send mail to the author(s) E-mail



Sign In