Rockford Lhotka's Blog

Home | Lhotka.net | CSLA .NET

 Friday, October 31, 2008

PDC 2008 was a lot of fun - a big show, with lots of announcements, lots of sessions and some thought-provoking content. I thought I'd through out a few observations. Not really conclusions, as those take time and reflection, so just some observations.

Windows Azure, the operating system for the cloud, is intriguing. For a first run at this, the technology seems surprisingly complete and contains a pretty reasonable set of features. I can easily see how web sites, XML services and both data-centric and compute-centric processing could be built for this platform. For that matter, it looks like it would be perhaps a week's work to get my web site ported over to run completely in Azure.

The real question is whether that would even make sense, and that comes down to the value proposition. One big component of value is price. Like anyone else, I pay a certain amount to run my web site. Electricity, bandwidth, support time, hardware costs, software costs, etc. I've never really sorted out an exact cost, but it isn't real high on a per-month basis. And I could host on any number of .NET-friendly hosting services that have been around for years, and some of them are pretty inexpensive. So the question becomes whether Azure will be priced in such a way that it is attractive to me. If so, I'm excited about Azure!! If not, then I really don't care about Azure.

I suspect most attendees went through a similar thought process. If Microsoft prices Azure for "the enterprise" then 90% of the developers in the world simply don't care about Azure. But if Microsoft prices Azure for small to mid-size businesses, and for the very small players (like me) then 90% of the developers in the world should (I think) really be looking at this technology

Windows 7 looks good to me. After the Tuesday keynote I was ready to install it now. As time goes by the urgency has faded a bit - Vista has stabilized nicely over the past 6-8 months and I really like it now. Windows 7 has some nice-sounding new features though. Probably the single biggest one is reduced system resource requirements. If Microsoft can deliver on that part of the promise I'll be totally thrilled. Though I really do want multi-monitor RDP and the ability to manage, mount (and even boot from) vhd files directly from the host OS.

In talking to friends of mine that work at Microsoft, my level of confidence in W7 is quite high. A couple of them have been running it for some time now, and while it is clearly pre-beta, they have found it to be a very satisfying experience. When I get back from all my travels I do think I'll have to buy a spare HD for my laptop and give it a try myself.

The Oslo modeling tools are also interesting, though they are more future-looking. Realistically this idea of model-driven development will require a major shift in how our industry thinks about and approaches custom software development. Such a massive shift will take many years to occur, regardless of whether the technology is there to enable it. It is admirable that Microsoft is taking such a gamble - building a set of tools and technologies for something that might become acceptable to developers in the murky future. Their gamble will pay off if we collectively decide that the world of 3GL development really is at an end and that we need to move to higher levels of abstraction. Of course we could decide to stick with what has (and hasn't) worked for 30+ years, in which case modeling tools will go the way of CASE.

But even if some of the really forward-looking modeling ideas never become palatable, many of the things Microsoft is doing to support modeling are immediately useful. Enhancements to Windows Workflow are a prime example, as is the M language. I've hard a hard time getting excited about WF, because it has felt like a graphical way to do FORTRAN. But some of the enhancements to WF directly address my primary concerns, and I can see myself getting much more interested in WF in the relatively near future. And the ability of the M language to define other languages (create DSLs), where I can create my own output generator to create whatever I need - now that is really, really cool!

Once I get done with my book and all my fall travel, you can bet I'll be exploring the use of M to create a specialized language to simplify the creation of CSLA .NET business classes :)

There were numerous talks about .NET 4.0 and the future of C# and VB.

Probably the single biggest thing on the language front is that Microsoft has finally decided to sync VB and C# so they have feature parity. Enough of this back-and-forth with different features, the languages will now just move forward together. A few years ago I would have argued against this, because competition breeds innovation. But today I don't think it matters, because the innovation is coming from F#, Ruby, Python and various other languages and initiatives. Both VB and C# have such massive pre-existing code-bases (all the code we've written) that they can't move rapidly or explore radical ideas - while some of these other languages are more free to do just that.

The framework itself has all sorts of changes and improvements. I spent less time looking at this than at Azure and Oslo though, so I honestly just don't have a lot to say on it right now. I look at .NET 4.0 and Visual Studio 2010 as being more tactical - things I'll spend a lot of time on over the next few months anyway - so I didn't see so much need to spend my time on it during PDC.

Finally, there were announcements around Silverlight and WPF. If anyone doubts that XAML is the future of the UI on Windows and (to some degree) the web, now is the time to wake up and smell the coffee. I'm obviously convinced Silverlight is going to rapidly become the default technology for building business apps, with WPF and Ajax as fallback positions, and everything at the PDC simply reinforced this viewpoint.

The new Silverlight and WPF toolkits provide better parity between the two XAML dialects, and show how aggressively Microsoft is working to achieve true parity.

But more important is the Silverlight intersection with Azure and Live Mesh. The fact that I can build smart client apps that totally host in Azure or the Mesh is compelling, and puts Silverlight a notch above WPF in terms of being the desired start-point for app development. Yes, I really like WPF, but even if it can host in Azure it probably won't host in Mesh, and in neither case will it be as clean or seamless.

So while I fully appreciate that WPF is good for that small percentage of business apps that need access to DirectX or rich client-side resources, I still think most business apps will work just fine with access to the monitor/keyboard/mouse/memory/CPU provided by Silverlight.

A couple people asked why I think Silverlight is better than Ajax. To me this is drop-dead simple. I can write a class in C# or VB that runs on the client in Silverlight. I can write real smart client applications that run in the browser. And I can run that exact same code on the server too. So I can give the user a very interactive experience, and then re-run that same code on the server because I don't trust the client.

To do that in Ajax you'd either have to write your code twice (in C# and in Javascript), or you'd have to do tons of server calls to simulate the interactivity provided by Silverlight - and that obviously won't scale nearly the same as the more correct Silverlight solution.

To me it is a no-brainer - Ajax loses when it comes to building interactive business apps like order entry screens, customer maintenance screens, etc.

That's not to say Ajax has no home. The web and browser world is really good at displaying data, and Ajax makes data display more interesting that simple HTML. I strongly suspect that most "Silverlight" apps will make heavy use of HTML/Ajax for data display, but I just can't see why anyone would willingly choose to create data entry forms or other interactive parts of their app outside of Silverlight.

And that wraps up my on-the-flight-home summary of thoughts about PDC.

Next week I'm speaking at the Patterns and Practices Summit in Redmond, and then I'll be at Tech Ed EMEA in Barcelona. I'm doing a number of sessions at both events, but what's cool is that at each event I'm doing a talk specifically about CSLA .NET for Silverlight. And in December I'll be at VS Live in Dallas, where I'll also give a talk directly on using CSLA .NET.

Friday, October 31, 2008 7:10:16 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  | 
 Friday, September 28, 2007

CSLA .NET version 3.0 adds support for Microsoft .NET 3.0 features. This ~120 page ebook covers how to use these new capabilities:

  • Windows Presentation Foundation (WPF)
    • Creating WPF forms using business objects
    • Using the new controls in the Csla.Wpf namespace
      • CslaDataProvider
      • Validator
      • Authorizer
      • ObjectStatus
      • IdentityConverter
    • Maximizing XAML and minimizing C#/VB code
  • Windows Communication Foundation (WCF)
    • Using the new WCF data portal channel to seamlessly upgrade from Remoting, Web services or Enterprise Services
    • Building WCF services using business objects
    • Applying WCF security to encrypt data on the wire
    • Sending username/password credentials to a WCF service
      • Including use of the new Csla.Security.PrincipalCache class
    • Using the DataContract attribute instead of the Serializable attribute
  • Windows Workflow Foundation (WF)
    • Creating activities using business objects
    • Invoking a workflow from a business object
    • Using the WorkflowManager class in the Csla.Workflow namespace

Version 3.0 is an additive update, meaning that you only need to use the .NET 3.0 features if you are using .NET 3.0. CSLA .NET 3.0 is useful for people using .NET 2.0!! These features include:

  • Enhancements to the validation subsystem
    • Friendly names for properties
    • Better null handling in the RegExMatch rule method
    • New StringMinLength rule method
    • Help for code generation through the DecoratedRuleArgs class
  • Data binding issues
    • Fixed numerous bugs in BusinessListBase to improve data binding behavior
    • Throw exception when edit levels get out of sync, making debugging easier
    • N-level undo changed to provide parity with Windows Forms data binding requirements
  • AutoCloneOnUpdate
    • Automatically clone objects when Save() is called, but only when data portal is local
  • Enhancements to the authorization subsystem
    • CanExecuteMethod() allows authorization for arbitrary methods

CSLA .NET 3.0 includes numerous bug fixes and some feature enhancements that benefit everyone. If you are using version 2.0 or 2.1, you should consider upgrading to 3.0 to gain these benefits, even if you aren't using .NET 3.0.

See the change logs for version 3.0, version 3.0.1 and version 3.0.2 for a more detailed list of changes.

Using CSLA .NET 3.0 is completely focused on how to use the new features in version 3.0. The book does not detail the internal changes to CSLA .NET itself, so all ~120 pages help you use the enhancements added since version 2.1.

Get the book at store.lhotka.net.
(C# available now, VB available in early October)

Download the 3.0.2 code from the CSLA .NET download page.

Books | CSLA .NET | WCF | Workflow | WPF
Friday, September 28, 2007 3:21:26 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  | 
 Wednesday, August 01, 2007

I wrote the following for the Using CSLA .NET 3.0 ebook, but I don't think I'm going to use it now, because I've wrapped most of this into a new class in CSLA .NET. Rather than letting this go to waste though, I thought I'd post it here. Remember that it is just draft content, so it may have typos or errors, but perhaps it will be useful to someone:

Basic Workflow Execution

Executing a workflow is a little tricky, because workflows default to running on a background thread. That means you must take steps to ensure that the workflow completes before the host process terminates.

One way to solve this issue is to always execute a workflow synchronously. Another is to use a thread synchronization object to prevent the process from terminating until the workflow completes.

Note: It is also possible to suspend and resume workflows, and even to unload them from memory so they store their state in a database. Later you can reload that workflow instance and resume it. These advanced scenarios are outside the scope of this book

Synchronous Execution

The code to synchronously execute a workflow follows a standard pattern:

1.      Create an instance of the WorkflowRuntime.

2.      Create a synchronization object.

3.      Set up event handlers.

4.      Create workflow instance.

5.      Ensure you have a valid principal object.

6.      Start the workflow.

7.      Wait for the workflow to complete.

The only step unique to CSLA .NET is number 5, and that is only required if you are using custom authentication. The WF runtime will automatically ensure that the background thread that executes the workflow has the same principal as the thread that calls the workflow’s Start() method, but you must ensure that the principal is set on the current thread before calling Start().

The following code implements these steps to execute the ProjectWorkflow implemented earlier in this chapter:

      using (WorkflowRuntime workflowRuntime = new WorkflowRuntime())

      {

        Exeception error = null;

 

        AutoResetEvent waitHandle = new AutoResetEvent(false);

        workflowRuntime.WorkflowCompleted +=

          delegate(object sender, WorkflowCompletedEventArgs e)

          {

             waitHandle.Set();

          };

        workflowRuntime.WorkflowTerminated +=

          delegate(object sender, WorkflowTerminatedEventArgs e)

          {

            error = e.Exception;

            waitHandle.Set();

          };

 

        // create workflow instance

        Dictionary<string,object> parameters = new Dictionary<string,object>();

        parameters.Add("ProjectId", projectId);

        WorkflowInstance instance =

          workflowRuntime.CreateWorkflow(

            typeof(PTWorkflow.ProjectWorkflow),

            parameters);

 

        // login before starting WF instance

        ProjectTracker.Library.Security.PTPrincipal.Login("pm", "pm");

 

        // execute workflow

        instance.Start();

 

        // wait for workflow to complete

        waitHandle.WaitOne();

 

        // throw any workflow exception

        if (error != null)

          throw error;

      }

Creating the workflow instance involves setting up a Dictionary<string, object> that contains name/value pairs for any parameters to be passed into th workflow instance:

        // create workflow instance

        Dictionary<string,object> parameters = new Dictionary<string,object>();

        parameters.Add("ProjectId", projectId);

        WorkflowInstance instance =

          workflowRuntime.CreateWorkflow(

            typeof(PTWorkflow.ProjectWorkflow),

            parameters);

The name in the dictionary must correspond to the name of a dependency property defined by the workflow, and of course the type of the value must match the dependency property type.

Keep in mind that creating an instance of a workflow does not start the workflow. The workflow won’t start executing until the Start() method is called later in the code.

The waitHandle synchronization object is the key to making this process synchronous. The waitHandle object starts out unset because false is passed to its constructor as its initial state:

        AutoResetEvent waitHandle = new AutoResetEvent(false);

At the bottom of the code is a line that calls WaitOne(), thus blocking the current thread until waitHandle is set:

        // execute workflow

        instance.Start();

 

        // wait for workflow to complete

        waitHandle.WaitOne();

While the current (starting) thread is blocked, the workflow is busy executing on a background thread. In other words, the Start() call returns immediately, having just started the workflow instance executing on a background thread. Without the WaitOne() call, the current thread would exit the code block, which would dispose the WF engine instance while it is executing the workflow. The result would be an exception.

Notice how the event handlers for the WorkflowCompleted and WorkflowTerminated events both call waitHandle.Set(). These events are raised by the WF engine when the workflow either completes or terminates unexpectedly. Either way, by calling the Set() method, the current thread is released so it can continue running.

In the case of a workflow terminating unexpectedly, the exception from the workflow is made available to the WorkflowTerminated event handler. You can choose what to do with this information as appropriate for your application. One technique is shown here, which is to store the Exception object in a field:

          delegate(object sender, WorkflowTerminatedEventArgs e)

          {

            error = e.Exception;

            waitHandle.Set();

          };

And then have the current thread throw the exception once it is unblocked:

        // wait for workflow to complete

        waitHandle.WaitOne();

 

        // throw any workflow exception

        if (error != null)

          throw error;

The result of this code is that the workflow appears to run synchronously, even though it really executes on a background thread.

Asynchronous Execution

Allowing a workflow to run asynchronously is just a slightly more complex version of running the workflow synchronously. The important thing is to ensure that your process doesn’t exit until the workflow is complete. This means that the synchronization object must be available at a broader scope so you can write code to prevent the application from closing if the workflow is still running.

You also must come up with a way to deal with any exception object in the case that the workflow terminates unexpectedly. One solution is to elevate the error field from the previous example to a broader scope as well.

Finally, the WorkflowRuntime instance must remain in memory until the workflow completes.

This means that you must define these fields so they exist at an application level, for instance using static fields:

  private static AutoResetEvent _waitHandle = null;

  private static Exception _workflowError = null;

  private static WorkflowRuntime _workflowRuntime = null;

Then you can create a method to start the workflow:

    public static void BeginWorkflow(Guid projectId)

    {

      _workflowRuntime = new WorkflowRuntime();

      _waitHandle = new AutoResetEvent(false);

      _workflowRuntime.WorkflowCompleted +=

        delegate(object sender, WorkflowCompletedEventArgs e)

        {

           _waitHandle.Set();

        };

      _workflowRuntime.WorkflowTerminated +=

        delegate(object sender, WorkflowTerminatedEventArgs e)

        {

          _workflowError = e.Exception;

          _waitHandle.Set();

        };

 

      // create workflow instance

      Dictionary<string,object> parameters = new Dictionary<string,object>();

      parameters.Add("ProjectId", projectId);

      WorkflowInstance instance =

        _workflowRuntime.CreateWorkflow(

          typeof(PTWorkflow.ProjectWorkflow),

          parameters);

 

      // login before starting WF instance

      ProjectTracker.Library.Security.PTPrincipal.Login("pm", "pm");

 

      // execute workflow

      instance.Start();

    }

Notice that the WorkflowRuntime object is no longer in a using block, so it can remain in memory, not disposed, while the workflow instance is running on the background thread.

The workflow instance is created the same as before, and its Start() method is called. At that point this method simply ends, returning to the caller.

Once you call BeginWorkflow() the workflow is started on a background thread, but your current thread (often the UI thread) is free to continue working.

The final piece to the puzzle is a method your application can call before it exits, or when it otherwise can’t continue without the workflow having completed:

    public static void EndWorkflow()

    {

      // wait for workflow to complete

      _waitHandle.WaitOne();

 

      // dispose runtime

      _workflowRuntime.Dispose();

 

      if (_workflowError != null)

        throw _workflowError;

    }

It is important to realize that this method will block the current thread until _waitHandle is set. If the workflow completes before this method is called, then _waitHandle is already set, and this method runs immediately, but if the workflow is still running, this method will block until the workflow completes or terminates.

For this to work, you must call EndWorkflow() before your process terminates to properly dispose the runtime and to determine if the workflow terminated unexpectedly.

 

Wednesday, August 01, 2007 4:15:26 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  | 
On this page....
Search
Archives
Feed your aggregator (RSS 2.0)
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