Task 5: Create a Tracking Profile
Tracking profiles are used to control the type of tracking information that the Windows Workflow Foundation runtime engine generates. By default, tracking information is saved for every workflow and activity event when you use a default profile.
In this task, you create a custom tracking profile that tracks all the workflow events and activity events, but only for the CodeActivity activities. Any other activities in the workflow do not generate any tracking information when this profile is used.
Note
Although you are encouraged to follow the exercises in a linear manner, it is not required. You can start this exercise by opening the sample project and proceeding to the steps in the following section.
To import the namespaces
In the Program source file, add the following directives to import the types that you must have for tracking profiles.
using System.IO; using System.Globalization; using System.Workflow.ComponentModel; using System.Workflow.Activities;
To create the tracking profile
In the Program class of your project, create a static method named CreateTrackingProfile.
Private Shared Sub CreateTrackingProfile() End Sub
static void CreateTrackingProfile() { }
In the CreateTrackingProfile method that you created in step 1, create a TrackingProfile object named profile and an ActivityTrackPoint object named trackPoint. Additionally, set the Version property of the TrackingProfile object equal to a new instance of a Version object, passing the string "1.0.0.0" as a parameter to the constructor.
TrackingProfile profile = new TrackingProfile(); ActivityTrackPoint trackPoint = new ActivityTrackPoint(); profile.Version = new Version("1.0.0.0");
Create an ActivityTrackingLocation object named location, passing in the Type of the CodeActivity activity as a parameter to the constructor.
// track CodeActivity activities only ActivityTrackingLocation location = new ActivityTrackingLocation (typeof(CodeActivity));
Enumerate through the values in the ActivityExecutionStatus enumerated data type, and add those values to the ExecutionStatusEvents collection that is defined in the ActivityTrackingLocation object.
// add all activity tracking events foreach (ActivityExecutionStatus s in Enum.GetValues(typeof(ActivityExecutionStatus))) { location.ExecutionStatusEvents.Add(s); }
Add the ActivityTrackingLocation object to the MatchingLocations collection that is defined in the ActivityTrackPoint object.
Add the ActivityTrackPoint object to the ActivityTrackPoints collection that is defined in the TrackingProfile object.
trackPoint.MatchingLocations.Add(location); profile.ActivityTrackPoints.Add(trackPoint);
Create a new WorkflowTrackPoint object named wtp and a WorkflowTrackingLocation object named wtl.
WorkflowTrackPoint wtp = new WorkflowTrackPoint(); WorkflowTrackingLocation wtl = new WorkflowTrackingLocation();
Enumerate through the TrackingWorkflowEvent enumerated data type, and add each value to the Events collection that is defined in the WorkflowTrackingLocation object.
// add all workflow tracking events foreach (TrackingWorkflowEvent s in Enum.GetValues(typeof(TrackingWorkflowEvent))) { wtl.Events.Add(s); }
Set the MatchingLocation property that is defined in the WorkflowTrackPoint object to the WorkflowTrackingLocation object.
Add the WorkflowTrackPoint object to the WorkflowTrackPoints collection that is defined in the TrackingProfile object.
wtp.MatchingLocation = wtl; profile.WorkflowTrackPoints.Add(wtp);
Create a new TrackingProfileSerializer object named serializer and a StringWriter object named writer.
// serialize tracking profile and save to SQL TrackingProfileSerializer serializer = new TrackingProfileSerializer(); StringWriter writer = new StringWriter(new StringBuilder(), CultureInfo.InvariantCulture);
Serialize the TrackingProfile object by calling the Serialize method that is defined in the TrackingProfileSerializer class.
Pass the StringWriter and TrackingProfile objects as parameters to that method.
serializer.Serialize(writer, profile);
Call the InsertTrackingProfile method, passing writer.ToString() as a parameter to that method.
Note
You create the InsertTrackingProfile method in the next procedure.
InsertTrackingProfile(writer.ToString());
In the Main method of the Program class, call the CreateTrackingProfile method you just created. This method should be called before you create the WorkflowRuntime object.
CreateTrackingProfile();
To save the tracking profile to a SQL database
In the Program class of your project, create a new static method named InsertTrackingProfile that takes a String named profile as a parameter.
Private Shared Sub InsertTrackingProfile(ByVal profile As String) End Sub
static void InsertTrackingProfile(string profile) { }
In the InsertTrackingProfile method, create a new SqlCommand object named cmd.
SqlCommand cmd = new SqlCommand();
Using the SqlCommand object that you created in the previous step, set the CommandType property to CommandType.StoredProcedure, set the CommandText property to "dbo.UpdateTrackingProfile".
Create a new SqlConnection object, passing Program.connectionString as a parameter to the constructor, and assign this object to the Connection property that is defined in the SqlCommand object.
cmd.CommandType = CommandType.StoredProcedure; cmd.CommandText = "dbo.UpdateTrackingProfile"; cmd.Connection = new SqlConnection(Program.connectionString);
Create a new try block and put the code for steps 6 through 15 in that block.
Create a new SqlParameter object named typFullName, and set its properties as shown in the following table.
Property Name Property Value ParameterName
"@TypeFullName"
SqlDbType
SqlDbType.NVarChar
SqlValue
typeof(Microsoft.Samples.Workflow.Tutorials.Hosting.HostingWorkflows).ToString();
Add the SqlParameter object to the Parameters collection that is defined in the SqlCommand object.
Your code for the typFullName object appears similar to the following code.
SqlParameter typFullName = new SqlParameter(); typFullName.ParameterName = "@TypeFullName"; typFullName.SqlDbType = SqlDbType.NVarChar; typFullName.SqlValue = typeof(HostingWorkflows).ToString(); cmd.Parameters.Add(typFullName);
Create a new SqlParameter object named assemblyFullName, and set its properties as outlined in the following table.
Property Name Property Value ParameterName
"@AssemblyFullName"
SqlDbType
SqlDbType.NVarChar
SqlValue
typeof(Microsoft.Samples.Workflow.Tutorials.Hosting.HostingWorkflows).Assembly.FullName
Add the SqlParameter object to the Parameters collection that is defined in the SqlCommand object.
Your code for the assemblyFullName object appears similar to the following code.
SqlParameter assemblyFullName = new SqlParameter(); assemblyFullName.ParameterName = "@AssemblyFullName"; assemblyFullName.SqlDbType = SqlDbType.NVarChar; assemblyFullName.SqlValue = typeof(HostingWorkflows).Assembly.FullName; cmd.Parameters.Add(assemblyFullName);
Create a new SqlParameter object named versionId, and set its properties as shown in the following table.
Property Name Property Value ParameterName
"@Version"
SqlDbType
SqlDbType.VarChar
SqlValue
"1.0.0.0"
Add the SqlParameter object to the Parameters collection that is defined in the SqlCommand object.
Your code for the versionId object appears similar to the following code.
SqlParameter versionId = new SqlParameter(); versionId.ParameterName = "@Version"; versionId.SqlDbType = SqlDbType.VarChar; versionId.SqlValue = "1.0.0.0"; cmd.Parameters.Add(versionId);
Create a new SqlParameter object named trackingProfile, and set its properties as shown in the following table.
Property Name Property Value ParameterName
"@TrackingProfileXml"
SqlDbType
SqlDbType.NVarChar
SqlValue
profile
Add the SqlParameter to the Parameters collection that is defined in the SqlCommand object.
Your code for the trackingProfile object appears similar to the following code.
SqlParameter trackingProfile = new SqlParameter(); trackingProfile.ParameterName = "@TrackingProfileXml"; trackingProfile.SqlDbType = SqlDbType.NVarChar; trackingProfile.SqlValue = profile; cmd.Parameters.Add(trackingProfile);
Call the Open method that is defined in the Connection property of the SqlCommand object.
Call the ExecuteNonQuery method that is defined in the SqlCommand object to run the stored procedure and save your tracking profile.
cmd.Connection.Open(); cmd.ExecuteNonQuery();
Create a new catch block for the SqlException exception following the try block that you created in steps 5 through 15.
In the catch block, use the WriteLine method to display the Message property that is defined in the SqlException object.
Additionally, add a message that explains the steps that are required to update the tracking profile with a new version number whenever the tracking profile is changed.
catch (SqlException e) { Console.WriteLine(e.Message); Console.WriteLine("The Tracking Profile was not inserted. " + "if you want to add a new Tracking Profile, modify the version " + "string in the profile by specifying a higher version number."); return; }
Create a finally block, and call the Close method followed by the Dispose method defined in the Connection property of the SqlCommand object.
finally { if ((null != cmd) && (null != cmd.Connection) && (ConnectionState.Closed != cmd.Connection.State)) { cmd.Connection.Close(); cmd.Connection.Dispose(); } }
Build your project and run it.
Your output appears similar to the following illustration.
Compiling the Code
For information about compiling your code, see Compiling the Code.
For a completed tutorial, see Completed Windows Workflow Foundation Runtime Hosting Tutorial.
See Also
Reference
System.Workflow.Runtime.Tracking
TrackingProfile
ActivityTrackPoint
ActivityExecutionStatus
ActivityTrackingLocation
WorkflowTrackPoint
WorkflowTrackingLocation
TrackingProfileSerializer
Concepts
Creating Custom Tracking Services
Creating and Using Tracking Profiles
Other Resources
Simple Tracking Example
Query Using SQLTrackingService
Tracking Using User Track Points
EventArgs Tracking Sample
ConsoleTrackingService Sample
Copyright © 2007 by Microsoft Corporation. All rights reserved.
Last Published: 2010-03-04