Wednesday, September 03, 2008

As part of the CSLA Light project we created a unit testing engine for Silverlight and donated it to the community as UnitDriven.

We now have our first community contribution to this open-source project, in the form of a really nice visual change. Here's the author's blog post on the topic:

http://staxmanade.blogspot.com/2008/08/unitdrivens-ui-gets-minor-makeover.html

Thank you Staxmanade! This is a really nice visual upgrade, and more importantly a major usability upgrade. I love it!

The next release of the CSLA Light unit tests will be linked to the new version of UnitDriven, and having used it for just a day or so, I can say it is a big help.

Wednesday, September 03, 2008 8:34:23 AM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  | 

 Monday, September 01, 2008

I have put an updated pre-release online for download of both CSLA .NET 3.6 and CSLA Light 3.6.

We're now at the point of focusing primarily on stabilization and limiting new features. Changes at this point will be due to our testing and usage, and feedback we recieve from the community.

This pre-release should be reasonably stable, on both the .NET and Silverlight platforms. Please give them a try and post in the forum with any issues you encounter. Thank you!

Monday, September 01, 2008 7:41:08 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [1]  | 

 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 [44]  | 

 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 [3]  | 

 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]  |