Search code examples
elsa-workflows

Bypass activity output to activity in switch case


I like the idea of activity inputs and outputs and prefer them over setting values in the workflow context. However I am now stuck with this approach when using switch cases. My workflow looks like this:

builder
  .ReceiveHttpPostRequest<ImportProducts>("/import")
  .Then<ExtractHttpRequestBodyActivity>()
  .Then<GetShopDataActivity>()
  .Switch(cases => cases
    .Add(
      context => context.GetInput<ShopData>()!.ShopType == "ShopType1",
      @case => @case
        .Then<GetShopType1ProductsActivity>()
        .Then<FilterShopType1ProductsActivity>()
        .Then<ConvertShopType1ProductsActivity>()))
  .Then<DebugActivity>();

Without the switch case the input of GetShopType1ProductsActivity is the output of GetShopDataActivity, but using switch case the input is null.

Is there a way to bypass the output to the first activity of the case?

Edit: I'm using Elsa 2.0.0-preview7.1545


Solution

  • There is no way to bypass Elsa form sending activity output automatically to another activity as input.

    That being said, it is up to you whether or not you use output/input.

    What you can do is this:

    1. Specify a name for GetShopDataActivity (using .WithName). E.g. "GetShopDataActivity1"
    2. Use the output of GetShopDataActivity Directly as input for GetShopType1ProductsActivity.

    To use output from a named activity, use the following code:

    context.GetOutputFrom<ShopData>("GetShopDataActivity1");
    

    An alternative approach is to store the output from GetShopDataActivity in a variable, then you can use that variable from other activities.

    Tip: when developing custom activities, try to expose their inputs. For example, if the GetShopType1ProductsActivity needs the output from GetShopDataActivity, instead of reading input directly from the activity context within that activity, consider exposing the necessary data using an "input" property, like so:

    [ActivityInput] public ShopData ShopData { get; set; }
    

    Then you can update your workflow as follows:

    builder
      .ReceiveHttpPostRequest<ImportProducts>("/import")
      .Then<ExtractHttpRequestBodyActivity>()
      .Then<GetShopDataActivity>().WithName("GetShopDataActivity1")
      .Switch(cases => cases
        .Add(
          context => context.GetInput<ShopData>()!.ShopType == "ShopType1",
          @case => @case
            .Then<GetShopType1ProductsActivity>(a => a.Set(x => x.ShopData, context => context.GetOutputFrom<ShopData>(""GetShopDataActivity1)))
            .Then<FilterShopType1ProductsActivity>()
            .Then<ConvertShopType1ProductsActivity>()))
      .Then<DebugActivity>();
    

    This could be cleaned up a bit by adding a couple of extension methods on your GetShopType1ProductsActivity class (more specifically, on ISetupActivity<GetShopType1ProductsActivity> called e.g. WithShopData.

    Additionally, if you need the output from GetShopDataActivity in multiple places (like you do already in at least two places), consider creating a an extension method that provides this information.

    For example:

    public static class ShoppingWorkflowExtensions
    {
       public static ShopData GetShopData(this ActivityExecutionContext context) => context => context.GetOutputFrom<ShopData>(""GetShopDataActivity1)!; 
    }
    

    You could then update your workflow like this:

    builder
      .ReceiveHttpPostRequest<ImportProducts>("/import")
      .Then<ExtractHttpRequestBodyActivity>()
      .Then<GetShopDataActivity>().WithName("GetShopDataActivity1")
      .Switch(cases => cases
        .Add(
          context => context.GetShopData().ShopType == "ShopType1",
          @case => @case
            .Then<GetShopType1ProductsActivity>(x => x.WithShopData(context => context.GetShopData()))
            .Then<FilterShopType1ProductsActivity>()
            .Then<ConvertShopType1ProductsActivity>()))
      .Then<DebugActivity>();