locked
How to find XAML path from inside an activity? RRS feed

  • Question

  • Hi,

    is it possible to find XAML path from inside a code activity which is part of that XAML? if yes how?


    haris
    Thursday, June 17, 2010 6:38 AM

Answers

  • Right, I think you will need to add your own runtime support in your host (code which loads the workflow).
    Workflow Instance Extensions would probably be an easy way to pass the information to your custom activity.
    Tim

    Friday, July 2, 2010 4:45 PM

All replies

  • [Misinterpreting question as XML node path]

    Maybe?

    If you load/save the XAML yourself, you can track the file state during the load, and use a dictionary to save path information of every activity loaded...

    I don't know if that helps you yet, I'm unclear on lots of details here, such as whether the activity is currently executing, or in designer, or how it relates to the xaml file... do you literally want a list of XML elements telling you wich way to go...? Maybe you can add some more details?

    Tim

    Friday, June 18, 2010 5:10 AM
  • ok, about the details. First I would like to know the XAML path at execution time of activity not at the time when activity is dropped into the designer.  Secondly regarding how activity relates to the XAML? basically user designed the workflow in re-hosted designer, dropped a few activities, saved the workflow and got the XAML output. Now the activity is inside the XAML or XAML contains the activity. Now at the time when user-designed workflow started executing, and control comes inside an activity I would like to some how find the path of XAML which contains this activity.
    haris
    Friday, June 18, 2010 6:13 AM
  • [Still misinterpreting the question]

    I think in general case this is nontrivial. A factor that can complicate the problem is that depending on how the workflow is constructed, a single workflow may map to multiple XAML files because of files involved in definition of activity class.

    But we might luckily only have the scenario where you know definitely know that your activity is in that file of interest, and that the root of the file of interest will correspond to the root of the workflow tree, then you could perhaps use this way of getting your workflow instance at runtime to grab the root

    http://blogs.msdn.com/b/tilovell/archive/2010/02/26/getting-your-workflow-instance.aspx

    Then, to figure out where your activity is in that file, reserialize the workflow instance using XamlServices.Save(new CustomXamlWriter(ActivityOfInterest)) where you create a CustomXamlWriter inheriting or wrapping XamlWriter that overrides it to provide tracking as mentioned above... and literally detect when you are serializing the object ActivityOfInterest.

    Serializing seems like the easiest way to ensure matching the exact activity, because you can do it by object ref. It sounds a bit heavy, I can just hope that someone else will suggest something much nicer... I guess to make it lighter you don't have to really serialize it to disk, you can just pretend to...

    Tim

    Friday, June 18, 2010 6:39 AM
  • Hi, Haris

    You cannot get the xaml file path from an sub-activity by default. However,you can get the xaml file path from the WorkflowDesigner.

     System.Activities.Presentation.WorkflowFileItem fileItem =
                    wd.Context.Items.GetValue(typeof(WorkflowFileItem)) as WorkflowFileItem; // wd is an instance of WorkflowDesigner
     String filePath=fileItem.LoadedFile;

    Regards


    This posting is provided "AS IS" with no warranties, and confers no rights. Microsoft Online Community Support My Blog:http://xhinker.com
    Monday, June 21, 2010 7:57 AM
  •  

    so there is no way to get XAML path from inside a code activity at its execution time? right?  just wants to make sure we are on same page..


    haris
    Monday, June 21, 2010 10:02 AM
  • Well in my use case XAML path have some business related importance.

    I have a simple workflow. User designs a workflow using a re-hosted workflow designer I am providing along with an application which can execute user designed workflows. The re-hosted designer contains some simple code based activities. Now when user executes the workflow using provided application/XAML executer, when execution reaches a code activity in the workflow, I would like to have something like.. context.GetExecutingXAMLPath().. Currently I am just trying to find an answer if it is possible or not .. yes or no..


    haris
    Tuesday, June 22, 2010 5:31 AM
  • Argh, I'm so sorry, I totally misunderstood the original question. Have you seen the Visual Workflow Tracking samples?

    http://blogs.msdn.com/b/kushals/archive/2009/12/22/visualworkflowtracking-aka-workflowsimulator.aspx

    I think System.Activities.Debugger.SourceLocationProvider.CollectMapping() might basically do what you want.

    Tim

    Tuesday, June 22, 2010 4:05 PM
  • I tried different approaches, looked at links posted in this thread but i couldn't achieve what I was trying to do so I am assuming it is not possible what I am trying to do. If there are any confusions about the scenario kindly let me know. And if my assumption is wrong that is it not possible kindly guide me how can I achieve this.

    In simple words I am trying to do this..

     public sealed class PathActivity : NativeActivity

        {

            protected override void Execute(NativeActivityContext context)

            {

    //at runtime when execution reaches here, I would like to get somehow the XAML path which contains this activity.

    // this XAML, which contain the 'PathActivity', will be designed using the re-hosted designer.

            }

        }


    haris
    Wednesday, June 23, 2010 9:07 AM
  • The 'Xaml Path' you are talking about - what exactly is it? Is it just the file name of the Xaml file? Or is it also about where the activity is located inside the Xaml document? (If so what would it look like?)

    And do you want it to mean 'path of the file used to load the entire currently executing workflow', or 'path of the file which contained this activity at designtime'?
    Tim

    Wednesday, June 23, 2010 3:49 PM
  • XAML path = XAML File path("C:\MyWorkflow.xaml)  in which workflow is persisted on the disk or in other words XAML file path which is output of re-hosted designer when we call workflowDesigner.Save() method. 

    I don't mean anything like specific path of that activity in a XAML file, I want disk path of XAML file in which my activity was dropped.

    If I understand your question correctly, in my case "path of the file used to load the entire currently executing workflow" and "path of the file which contained this activity at design time" are same. My activity is a code based activity and when user designed the workflow using re-hosted designer he/she would drop the activity in the designer and will save the workflow in XAML file format. Later on that XAML file will be used to initiate execute the workflow. I want path of this XAML file at execution time of activity.

     


    haris
    Thursday, June 24, 2010 6:02 AM
  • I'm glad I finally asked.

    Seems like System.Activities.Debugger.SourceLocationProvider.CollectMapping() might not do what I thought it did either, I hadn't noticed you need to pass it the file path. Sorry about that bad suggestion.

    But - I do see other possible opportunities...

    One is - who invokes this workflow in the first place? If you're the one invoking it, you could smuggle the data to the custom activity in your workflow using workflow extensions.

    Opportunity two is to figure out how to read the debugger file name attribute that gets saved in most Activity XAMLs...

    For that, please try this (based on the Getting your instance activity mentioned earlier) :

    public sealed class GetRootExecutionXamlPath : NativeActivity<string>
      {
        public class WorkflowInstanceInfo : IWorkflowInstanceExtension
        {
          public IEnumerable<object> GetAdditionalExtensions()
          {
            yield break;
          }
    
    
          public void SetInstance(WorkflowInstanceProxy instance)
          {
            this.proxy = instance;
          }
    
    
          WorkflowInstanceProxy proxy;
    
    
          public WorkflowInstanceProxy GetProxy() { return proxy; }
        }
    
    
        protected override void Execute(NativeActivityContext context)
        {
          WorkflowInstanceProxy proxy = context.GetExtension<WorkflowInstanceInfo>().GetProxy();
          Activity root = proxy.WorkflowDefinition;
    
          object filename = System.Activities.Debugger.XamlDebuggerXmlReader.GetFileName(root);
          if (String.IsNullOrEmpty((string)filename))
          {
            Activity rootChild = WorkflowInspectionServices.GetActivities(root).ElementAt(0);
            filename = System.Activities.Debugger.XamlDebuggerXmlReader.GetFileName(rootChild);
          }
          Result.Set(context, filename.ToString());
        }
    
        protected override void CacheMetadata(NativeActivityMetadata metadata)
        {
          base.CacheMetadata(metadata);
          metadata.AddDefaultExtensionProvider<WorkflowInstanceInfo>(() => new WorkflowInstanceInfo());
        }
      }

    Tim

    • Proposed as answer by Tim Lovell-Smith Thursday, June 24, 2010 4:25 PM
    • Marked as answer by haris hasan Friday, June 25, 2010 6:41 AM
    • Unmarked as answer by haris hasan Friday, July 2, 2010 1:35 PM
    Thursday, June 24, 2010 4:24 PM
  • Thanx A lot :) It finally worked. I apologize that I wasn't very clear in problem's description earlier and couldn't make you understand what I was trying to do.
    haris
    Friday, June 25, 2010 6:41 AM
  • Not your fault! I think I should always check to make sure I understand the question first.

    Tim

    Friday, June 25, 2010 3:30 PM
  • Ok, first of all my apologies that I couldn't work on this issue at that time(when you suggested the solution) so I couldn't find the issues involved with the approach you suggested.

    I am facing following issues while trying to find the XAML path from inside an activity at runtime...

    When I create a workflow using VS's standard designer, XAML file stores this information "XamlDebuggerXmlReader.FileName="E:\Visual Studio 2010\Projects\MyProjectName\WorkflowConsoleApplication1\Workflow1.xaml" inside it. At execution time of activity, using the method you suggested, I was able to extract this path from XAML.

    Now lets suppose I move my XAML file to a new directory, lets say "D:\Workflow1.xaml". Problem is XAML file still contains the older path "E:\Visual Studio 2010\Projects\MyProjectName\WorkflowConsoleApplication1\Workflow1.xaml" which is incorrect as my workflow actually exists at another location. So I am getting incorrect XAML file path.

    Another issue is that when I design the workflow using re-hosted workflow designer, the output XAML file doesn't contains anything like "XamlDebuggerXmlReader.FileName="E:\Visual Studio 2010\Projects\MyProjectName\WorkflowConsoleApplication1\Workflow1.xaml". So in that case, code always remain unsuccessful in finding the XAML path.

    Kindly help me in trying to find a better solution..

     

    Let me know if you have any confusion/question about the scenario.

     


    haris
    Friday, July 2, 2010 1:37 PM
  • Hi Haris,

    I think you will need to record the data yourself at the time when you start executing the workflow. How are you invoking the workflow, are you calling WorkflowApplication.Load yourself, or using IIS, WorkflowServiceHost etc?

    Tim

    Friday, July 2, 2010 4:19 PM
  • I am loading and executing workflow by myself. I simply load the XAML file in an activity and then I create WorkflowApplication object using previously created activity and then I call WorkflowApplication object's run method.

     

    So does that mean it is not possible what I am trying to do? not possible through some built in functionality, I would have to do something by myself at design or runtime. Right?

     


    haris
    Friday, July 2, 2010 4:37 PM
  • Right, I think you will need to add your own runtime support in your host (code which loads the workflow).
    Workflow Instance Extensions would probably be an easy way to pass the information to your custom activity.
    Tim

    Friday, July 2, 2010 4:45 PM