locked
Help getting Transitions from StateMachine using WorkflowServiceHost RRS feed

  • Question

  • Hi folks

    Can I create a WorkflowServiceHost that will host a StateMachine activity at the root and also provide an additional endpoint within that host that will allow me to Get the current transitions avaliable from a given state? I have tried to create a custom endpoint but I have only been able to specify the service contract for the desired endpoint actions and been unsuccessful with the implementation.

    I used the following method to get transitions for a given state in the StateMachine Activity in a WorkflowApplication however I cannot figure out where I can expose this as a WCF operation from my WSH.

            public List<Transition> GetTransitionsFromState(string stateDisplayName)
            {
                IEnumerable<Activity> activitiesInWorkflow = WorkflowInspectionServices.GetActivities(new StateMachineWorkflow());
                var transitionsFromState = new List<Transition>();
     
                foreach (var activity in activitiesInWorkflow)
                {
                    if (activity is StateMachine)
                    {
                        StateMachine stateMachine = activity as StateMachine;
                        var states = stateMachine.States;
                        foreach (var state in states)
                        {
                            if (state.DisplayName == stateDisplayName)
                            {
                                transitionsFromState = state.Transitions.ToList(); break;
                            }
                        }
                        break;
                    }
                }
                return transitionsFromState;
            }

     

    Thanks in advance.

    Stephen





    • Edited by SDMIT Wednesday, November 16, 2011 6:26 PM
    Tuesday, November 15, 2011 6:03 PM

Answers

  • Hi,

    You can expose it by using a self-host WCF service, the code looks like:

    using System;
    using System.Linq;
    using System.Activities;
    using System.Activities.Statements;
    using System.Collections.Generic;
    using System.ServiceModel;
    using System.ServiceModel.Description;
    using System.Runtime.Serialization;
    using System.Text;

    namespace StateMachineConsoleApp
    {

        class Program
        {
            static void Main(string[] args)
            {
                Uri baseAddress = new Uri("http://localhost:8080/ExposeTransition");

                // Create the ServiceHost.
                using (ServiceHost host = new ServiceHost(typeof(ExposeTransition), baseAddress))
                {
                    // Enable metadata publishing.
                    ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
                    smb.HttpGetEnabled = true;
                    smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
                    host.Description.Behaviors.Add(smb);

                    // Open the ServiceHost to start listening for messages. Since
                    // no endpoints are explicitly configured, the runtime will create
                    // one endpoint per base address for each service contract implemented
                    // by the service.
                    host.Open();

                    Console.WriteLine("The service is ready at {0}", baseAddress);
                    Console.WriteLine("Press <Enter> to stop the service.");
                    Console.ReadLine();
                    host.Close();
                }

              
            }
        }
        [ServiceContract]
        public class ExposeTransition
        {
            [OperationContract]
            public List<TransitionModel> getlist(string stateDisplayName)
            {
                List<Transition> ListTransistions = GetTransitionsFromState(stateDisplayName);
                List<TransitionModel> ListModes = new List<TransitionModel>();

                foreach (Transition item in ListTransistions)
                {
                    TransitionModel model = new TransitionModel();
                    model.DisplayName = item.DisplayName;
                    if (item.To != null)
                    {
                        model.ToStateName = item.To.DisplayName;
                    }
                    if (item.Trigger != null)
                    {
                        model.TriggerName = item.Trigger.DisplayName;
                    }

                    ListModes.Add(model);

                }

                return ListModes;

            }
            public static List<Transition> GetTransitionsFromState(string stateDisplayName)
            {
                IEnumerable<Activity> activitiesInWorkflow = WorkflowInspectionServices.GetActivities(new StateMachineWorkflow());
                var transitionsFromState = new List<Transition>();

                foreach (var activity in activitiesInWorkflow)
                {
                    if (activity is StateMachine)
                    {
                        StateMachine stateMachine = activity as StateMachine;
                        var states = stateMachine.States;
                        foreach (var state in states)
                        {
                            if (state.DisplayName == stateDisplayName)
                            {
                                transitionsFromState = state.Transitions.ToList(); break;
                            }
                        }
                        break;
                    }
                }
                return transitionsFromState;
            }
        }
        [DataContract]
        public class TransitionModel
        {
            string displayName;
            string toStateName;
            string triggerName;

            [DataMember]
            public string DisplayName
            {
                get { return displayName; }
                set { displayName = value; }
            }

            [DataMember]
            public string ToStateName
            {
                get { return toStateName; }
                set { toStateName = value; }
            }

            [DataMember]
            public string TriggerName
            {
                get { return triggerName; }
                set { triggerName = value; }
            }
        }
    }

    If you want expose it by using WCF Workflow service, you can use RecieveAndSendReply activity combined with code activity to fit your requirement.


    Leo Tang [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    • Marked as answer by SDMIT Thursday, November 17, 2011 2:09 PM
    Thursday, November 17, 2011 11:04 AM

All replies

  • Hi,

    You can expose it by using a self-host WCF service, the code looks like:

    using System;
    using System.Linq;
    using System.Activities;
    using System.Activities.Statements;
    using System.Collections.Generic;
    using System.ServiceModel;
    using System.ServiceModel.Description;
    using System.Runtime.Serialization;
    using System.Text;

    namespace StateMachineConsoleApp
    {

        class Program
        {
            static void Main(string[] args)
            {
                Uri baseAddress = new Uri("http://localhost:8080/ExposeTransition");

                // Create the ServiceHost.
                using (ServiceHost host = new ServiceHost(typeof(ExposeTransition), baseAddress))
                {
                    // Enable metadata publishing.
                    ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
                    smb.HttpGetEnabled = true;
                    smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
                    host.Description.Behaviors.Add(smb);

                    // Open the ServiceHost to start listening for messages. Since
                    // no endpoints are explicitly configured, the runtime will create
                    // one endpoint per base address for each service contract implemented
                    // by the service.
                    host.Open();

                    Console.WriteLine("The service is ready at {0}", baseAddress);
                    Console.WriteLine("Press <Enter> to stop the service.");
                    Console.ReadLine();
                    host.Close();
                }

              
            }
        }
        [ServiceContract]
        public class ExposeTransition
        {
            [OperationContract]
            public List<TransitionModel> getlist(string stateDisplayName)
            {
                List<Transition> ListTransistions = GetTransitionsFromState(stateDisplayName);
                List<TransitionModel> ListModes = new List<TransitionModel>();

                foreach (Transition item in ListTransistions)
                {
                    TransitionModel model = new TransitionModel();
                    model.DisplayName = item.DisplayName;
                    if (item.To != null)
                    {
                        model.ToStateName = item.To.DisplayName;
                    }
                    if (item.Trigger != null)
                    {
                        model.TriggerName = item.Trigger.DisplayName;
                    }

                    ListModes.Add(model);

                }

                return ListModes;

            }
            public static List<Transition> GetTransitionsFromState(string stateDisplayName)
            {
                IEnumerable<Activity> activitiesInWorkflow = WorkflowInspectionServices.GetActivities(new StateMachineWorkflow());
                var transitionsFromState = new List<Transition>();

                foreach (var activity in activitiesInWorkflow)
                {
                    if (activity is StateMachine)
                    {
                        StateMachine stateMachine = activity as StateMachine;
                        var states = stateMachine.States;
                        foreach (var state in states)
                        {
                            if (state.DisplayName == stateDisplayName)
                            {
                                transitionsFromState = state.Transitions.ToList(); break;
                            }
                        }
                        break;
                    }
                }
                return transitionsFromState;
            }
        }
        [DataContract]
        public class TransitionModel
        {
            string displayName;
            string toStateName;
            string triggerName;

            [DataMember]
            public string DisplayName
            {
                get { return displayName; }
                set { displayName = value; }
            }

            [DataMember]
            public string ToStateName
            {
                get { return toStateName; }
                set { toStateName = value; }
            }

            [DataMember]
            public string TriggerName
            {
                get { return triggerName; }
                set { triggerName = value; }
            }
        }
    }

    If you want expose it by using WCF Workflow service, you can use RecieveAndSendReply activity combined with code activity to fit your requirement.


    Leo Tang [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    • Marked as answer by SDMIT Thursday, November 17, 2011 2:09 PM
    Thursday, November 17, 2011 11:04 AM
  • Leo you're a legend!

    Thanks for the additional transition model code to. A little question though, lets say if the WorkflowServiceHost has already been created at this point by passing in an activity to its constructor. Is there any way to inject the above code in to an exisiting ServiceHost or would I require a seperate host to manage the other?

    Thursday, November 17, 2011 1:28 PM