Archive for the ‘workflow’ Category

Pro WF for .NET 3.5

April 12, 2008

So my last post to this blog was back in November. I’ve been very busy working on an updated version of my Pro WF book. The new edition of my book was originally scheduled for availability in late July, but that date has now been moved up to June 23rd.

The new edition provides coverage of the new WF features in .NET 3.5 and includes two new chapters. One of the new chapters covers WF and WCF integration (workflow services). The other new chapter provides better coverage of building custom composite activities and handling long-running tasks. I’ve also reviewed and updated all of the example code, the text and the screen shots.

Visual Studio 2008 now available

November 20, 2007

After a long wait, Visual Studio 2008 (formerly known as Orcas) is now available. I’ve been using beta 2 for some time now and it’s been very stable. .NET 3.5 is also included with VS 2008. I’ll now have to find a spare day to uninstall the beta and install RTM.

Here are a few pertinent links:

http://msdn2.microsoft.com/en-us/vstudio/default.aspx

http://msdn2.microsoft.com/en-us/subscriptions/bb608344.aspx

http://www.microsoft.com/express/

Let the downloading begin!

Pro WF on sale at Bookpool

October 2, 2007

Bookpool.com has all Apress books on sale at 50% off list price. It’s a great time to pick up my Pro WF book if you don’t already have it. Since it’s also published by Apress, my .NET Interop recipes book is also on sale.

Activity Validation for Bound Properties

September 27, 2007

One of the readers (Andrew) of my Pro WF book recently had a question about page 114 of the book. This page contains the code for a custom activity validator class that enforces design-time requirements. In this example, I wanted to make sure that two properties of the target activity were set at design-time.

Andrew pointed out that the code only accepts statically set values for the properties. If you set these dependency properties by binding them to another property, the validation fails. He’s right. That particular example code only demonstrates how to validate against statically set values.

To solve the problem, all you need to do is call the IsBindingSet method of the base Activity class. Here is the revised code from page 114 (Listing 3-11) that now works for statically set or bound property values:

using System;
using System.Workflow.ComponentModel.Compiler;

namespace CustomActivityComponents
{
    /// <summary>
    /// Validator for MyCustomActivity
    /// </summary>
    public class MyCustomActivityValidator : ActivityValidator
    {
        public override ValidationErrorCollection Validate(
            ValidationManager manager, object obj)
        {
            ValidationErrorCollection errors = base.Validate(manager, obj);
            //only validate a single custom activity type
            if (obj is MyCustomActivity)
            {
                MyCustomActivity activity = obj as MyCustomActivity;
                //only do validation when the activity is in a workflow
                if (activity.Parent != null)
                {
                    if (activity.MyInt == 0)
                    {
                        if (!activity.IsBindingSet(MyCustomActivity.MyIntProperty))
                        {
                            errors.Add(
                                ValidationError.GetNotSetValidationError(
                                    “MyInt”));
                        }
                    }

                    if (activity.MyString == null ||
                        activity.MyString.Length == 0)
                    {
                        if (!activity.IsBindingSet(MyCustomActivity.MyStringProperty))
                        {
                            errors.Add(new ValidationError(
                                “MyString Property is incorrect”, 501));
                        }
                    }
                }
            }
            return errors;
        }
    }
}

Visual Studio 2008 (Orcas) Feature: Instantiating Objects in WF Rules

August 28, 2007

One of the new WF-related features in Visual Studio 2008 (Orcas) is the ability to new-up objects from within a rule. Previously, this seemingly simple task of creating a new object wasn’t possible within a rule. Now it is.

To illustrate this new feature, consider the following contrived example. Assume that you have a workflow that must return an instance of the following class:

using System;

namespace NewUpRules
{
    /// <summary>
    /// Just a test class that is instantiated by a rule
    /// </summary>
    public class MyClass
    {
        public MyClass(String dayOfWeekDesc)
        {
            _dayOfWeekDesc = dayOfWeekDesc;
        }

        private String _dayOfWeekDesc;
        public String DayOfWeekDesc
        {
            get { return _dayOfWeekDesc; }
            set { _dayOfWeekDesc = value; }
        }
    }
}

Previously, your workflow could use a PolicyActivity and implement a few rules, but you would have to create an instance of this class in code instead of in the rule. However, now you can implement a rule that directly creates an instance of the object like this:

Condition:
System.DateTime.Now.DayOfWeek == System.DayOfWeek.Monday
Then Actions:
this.MyWFResult = new NewUpRules.MyClass(”Starting a new work week”)
Else Actions:
this.MyWFResult = new NewUpRules.MyClass(”Some other day”)

The MyWFResult variable is assumed to be a workflow variable that is used to return the resulting instance of MyClass to the host application.

But you’re not limited to creating objects in the rule actions. You can also new-up objects in the Condition portion of the rule. Consider this class:

using System;

namespace NewUpRules
{
    /// <summary>
    /// Another class used within a rule
    /// </summary>
    public class MyDayOfWeekChecker
    {
        private DateTime _dateToCheck;
        public MyDayOfWeekChecker(DateTime value)
        {
            _dateToCheck = value;
        }

        public Boolean IsStartOfWorkWeek
        {
            get
            {
                return (_dateToCheck.DayOfWeek == DayOfWeek.Monday);
            }
        }
    }
}

A DateTime value is passed to the constructor of this class, and an IsStartOfWorkWeek property is defined which returns a Boolean. With the VS 2008 enhancements, you can now create an instance of this class and use it in a rule condition like this:

Condition:
new NewUpRules.MyDayOfWeekChecker(System.DateTime.Now).IsStartOfWorkWeek
Then Actions:
this.MyWFResult = new NewUpRules.MyClass(”Starting a new work week”)
Else Actions:
this.MyWFResult = new NewUpRules.MyClass(”Some other day”)

Granted, this isn’t the most exciting new feature in Orcas, but I do think it is a welcomed change that improves the rules capabilities in WF. Note: All of this code works in Beta 2 of Orcas.

Another reference

July 25, 2007

Oops…In my last post, I missed this reference to my Pro WF book:

http://spsfactory.blogspot.com/2007/07/bruces-fantastic-pro-wf-windows.html

Maybe there are others out there that I just haven’t found yet.  If you’ve referenced my book on your blog or site, I’d love to know about it.

A quick search

July 21, 2007

Orcas Beta 1

June 23, 2007

I realize this isn’t exactly the latest ground-break news, but the Orcas beta 1 is now available here.  I’ve downloaded and installed the beta but haven’t had the chance to really get into it yet.  I’m looking forward to trying out some of the new WF features, including the WCF/WF integration.

Persistence and Tracking together

May 23, 2007

A reader of my workflow book recently wrote me with a question about the standard persistence and tracking services. Their question concerned how to use both of these standard services at the same time. Specifically, they wanted to know how to specify two different database connection strings in the App.config.

There’s really two separate questions there. First, how do you specify two different connection strings for the services, presumably pointing to two different databases. Second, is that how you should use these two services together?

To answer the first question, you can specify the connection string in either the CommonParameters section of the App.Config, or inline as an attribute of the service itself.

For example, here is an App.Config that provides two different database connection strings, one for each service:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="WorkflowRuntime"
      type="System.Workflow.Runtime.Configuration.WorkflowRuntimeSection,
        System.Workflow.Runtime, Version=3.0.00000.0, Culture=neutral,
        PublicKeyToken=31bf3856ad364e35" />
  </configSections>
  <WorkflowRuntime>
    <Services>
      <add type="System.Workflow.Runtime.Tracking.SqlTrackingService,
        System.Workflow.Runtime, Version=3.0.00000.0, Culture=neutral,
        PublicKeyToken=31bf3856ad364e35"
           ConnectionString="Initial Catalog=WorkflowTracking;
             Data Source=localhostSQLEXPRESS;
             Integrated Security=SSPI;" />
      <add type="System.Workflow.Runtime.Hosting.SqlWorkflowPersistenceService,
        System.Workflow.Runtime, Version=3.0.00000.0,
        Culture=neutral, PublicKeyToken=31bf3856ad364e35"
        UnloadOnIdle="true" LoadIntervalSeconds="5"
          ConnectionString="Initial Catalog=WorkflowPersistence;
             Data Source=localhostSQLEXPRESS;
             Integrated Security=SSPI;" />
    </Services>
  </WorkflowRuntime>
</configuration>

That answers the first question. However, that’s not the recommended way to use the standard persistence and tracking services at the same time. Instead, you should use the same database for persistence and tracking. One database means one connection string. And WF provides a special service named SharedConnectionWorkflowCommitWorkBatchService that you should also load. This service is optimized for use with the standard persistence and tracking services. It uses the same database connection for both services, avoiding the use of MSDTC that would otherwise be needed.

Here’s a revised App.config that loads the special commit work batch service and uses the same database for persistence and tracking. Since a single connection string is used for both services, it is moved back to the CommonParameters section of the App.config.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="WorkflowRuntime"
      type="System.Workflow.Runtime.Configuration.WorkflowRuntimeSection,
        System.Workflow.Runtime, Version=3.0.00000.0, Culture=neutral,
        PublicKeyToken=31bf3856ad364e35" />
  </configSections>
  <WorkflowRuntime>
    <CommonParameters>
      <add name="ConnectionString"
           value="Initial Catalog=Workflow;
             Data Source=localhostSQLEXPRESS;
             Integrated Security=SSPI;" />
    </CommonParameters>
    <Services>
      <add type="System.Workflow.Runtime.Hosting.SharedConnectionWorkflowCommitWorkBatchService,
            System.Workflow.Runtime, Version=3.0.00000.0, Culture=neutral,
            PublicKeyToken=31bf3856ad364e35" />
      <add type="System.Workflow.Runtime.Tracking.SqlTrackingService,
        System.Workflow.Runtime, Version=3.0.00000.0, Culture=neutral,
        PublicKeyToken=31bf3856ad364e35" />
      <add type="System.Workflow.Runtime.Hosting.SqlWorkflowPersistenceService,
        System.Workflow.Runtime, Version=3.0.00000.0,
        Culture=neutral, PublicKeyToken=31bf3856ad364e35"
        UnloadOnIdle="true" LoadIntervalSeconds="5" />
    </Services>
  </WorkflowRuntime>
</configuration>

Sample Workflow Persistence chapter

March 19, 2007

Apress has made Chapter 8 of my Pro WF book available for download in PDF format. This is the chapter that covers workflow persistence. You can obtain this sample chapter from the Apress page for this book, or directly from this site.