Search code examples
customizationworkflow-foundation-4workflow-activity

Workflow XAML Custom Activity Parsing issue?


I've created a custom XAML Activity inherited from NativeActivity and IActivityTemplateFactory The Designer shows the correct look and feel inside the Library I've defined.

However when I drop it on the Flow Surface of a workflow Console Application I don't see it rendered. The CPU pegs at 50% and if I run procmon.exe I see BUFFEROVERFLOW on the .XAML file and a NOT REPARSE error on the exe itself.

I do have the typeof Designer defined as the attribute of the class.

I've turned on Exceptions in the VS debug to see if an exception is being thrown but nothing ever comes out.

--CODE-- CS

[Designer(typeof(ITCRetryActivityDesigner))]   
public sealed class ITCRetryActivity : NativeActivity, IActivityTemplateFactory
{
    private static readonly TimeSpan DefaultRetryInterval = new TimeSpan(0, 0, 0, 1);

    private readonly Variable<Int32> _attemptCount = new Variable<Int32>();

    private readonly Variable<TimeSpan> _delayDuration = new Variable<TimeSpan>();

    private readonly Delay _internalDelay;

    public ITCRetryActivity()
    {
        _internalDelay = new Delay
        {
            Duration = new InArgument<TimeSpan>(_delayDuration)
        };
        Body = new ActivityAction();
        MaxAttempts = 5;
        ExceptionType = typeof(TimeoutException);
        RetryInterval = DefaultRetryInterval;                
    }

    [DebuggerNonUserCode]
    public Activity Create(DependencyObject target)
    {
        return new ITCRetryActivity
               {
                   Body =
                       {
                           Handler = new Sequence()
                       }
               };
    }

    protected override void CacheMetadata(NativeActivityMetadata metadata)
    {
        metadata.AddDelegate(Body);
        metadata.AddImplementationChild(_internalDelay);
        metadata.AddImplementationVariable(_attemptCount);
        metadata.AddImplementationVariable(_delayDuration);

        RuntimeArgument maxAttemptsArgument = new RuntimeArgument("MaxAttempts", typeof(Int32), ArgumentDirection.In, true);
        RuntimeArgument retryIntervalArgument = new RuntimeArgument("RetryInterval", typeof(TimeSpan), ArgumentDirection.In, true);

        metadata.Bind(MaxAttempts, maxAttemptsArgument);
        metadata.Bind(RetryInterval, retryIntervalArgument);

        Collection<RuntimeArgument> arguments = new Collection<RuntimeArgument>
                                                {
                                                    maxAttemptsArgument,
                                                    retryIntervalArgument
                                                };

        metadata.SetArgumentsCollection(arguments);
        ValidationError validationError;

        if (Body == null)
        {
            validationError = new ValidationError("No Children are defined in this Retry Activity", true, "Body"); 
            metadata.AddValidationError(validationError);
        }

        if (typeof (Exception).IsAssignableFrom(ExceptionType) != false) return;
        validationError = new ValidationError("Exception type does not match", false, "ExceptionType");

        metadata.AddValidationError(validationError);
    }

    protected override void Execute(NativeActivityContext context)
    {
        ExecuteAttempt(context);
    }

    private static Boolean ShouldRetryAction(Type exceptionType, Exception thrownException)
    {
        return exceptionType != null && exceptionType.IsInstanceOfType(thrownException);
    }

    private void ActionFailed(NativeActivityFaultContext faultcontext, Exception propagatedexception, ActivityInstance propagatedfrom)
    {
        Int32 currentAttemptCount = _attemptCount.Get(faultcontext);

        currentAttemptCount++;

        _attemptCount.Set(faultcontext, currentAttemptCount);

        Int32 maxAttempts = MaxAttempts.Get(faultcontext);

        if (currentAttemptCount >= maxAttempts)
        {
            // There are no further attempts to make
            return;
        }

        if (ShouldRetryAction(ExceptionType, propagatedexception) == false)
        {
            return;
        }

        faultcontext.CancelChild(propagatedfrom);
        faultcontext.HandleFault();

        TimeSpan retryInterval = RetryInterval.Get(faultcontext);

        if (retryInterval == TimeSpan.Zero)
        {
            ExecuteAttempt(faultcontext);
        }
        else
        {
            // We are going to wait before trying again
            _delayDuration.Set(faultcontext, retryInterval);

            faultcontext.ScheduleActivity(_internalDelay, DelayCompleted);
        }
    }

    private void DelayCompleted(NativeActivityContext context, ActivityInstance completedinstance)
    {
        ExecuteAttempt(context);
    }

    private void ExecuteAttempt(NativeActivityContext context)
    {
        if (Body == null)
        {
            return;
        }

        context.ScheduleAction(Body, null, ActionFailed);
    }

    [Browsable(false)]
    public ActivityAction Body
    {
        get;
        set;
    }

    [DefaultValue(typeof(TimeoutException))]
    public Type ExceptionType
    {
        get;
        set;
    }

    public InArgument<Int32> MaxAttempts
    {
        get;
        set;
    }

    public InArgument<TimeSpan> RetryInterval
    {
        get;
        set;
    }
}
}

--XAML--

<sap:ActivityDesigner x:Class="ITC.Common.Workflow.ITCRetryActivityDesigner"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sap="clr-namespace:System.Activities.Presentation;assembly=System.Activities.Presentation"
xmlns:sapv="clr-namespace:System.Activities.Presentation.View;assembly=System.Activities.Presentation"
xmlns:conv="clr-namespace:System.Activities.Presentation.Converters;assembly=System.Activities.Presentation">
<sap:ActivityDesigner.Icon>
    <DrawingBrush>
        <DrawingBrush.Drawing>
            <ImageDrawing>
                <ImageDrawing.Rect>
                    <Rect Location="0,0"
                          Size="16,16">
                    </Rect>
                </ImageDrawing.Rect>
                <ImageDrawing.ImageSource>
                    <BitmapImage UriSource="d-metal-reload-arrows.jpg"></BitmapImage>
                </ImageDrawing.ImageSource>
            </ImageDrawing>
        </DrawingBrush.Drawing>
    </DrawingBrush>
</sap:ActivityDesigner.Icon>
<sap:ActivityDesigner.Resources>
    <conv:ModelToObjectValueConverter x:Key="ModelItemConverter"
                                      x:Uid="sadm:ModelToObjectValueConverter_1" />
    <DataTemplate x:Key="Collapsed">
        <TextBlock HorizontalAlignment="Center"
                   FontStyle="Italic"
                   Foreground="Gray">
            Double-Click to View
        </TextBlock>
    </DataTemplate>
    <DataTemplate x:Key="Expanded">
        <StackPanel Orientation="Vertical">
            <Grid Name="contentGrid">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto" />
                    <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition />
                </Grid.RowDefinitions>

                <TextBlock Grid.Row="0"
                           Grid.Column="0"
                           HorizontalAlignment="Left"
                           VerticalAlignment="Center">
                    Exception Type:
                </TextBlock>
                <sapv:TypePresenter HorizontalAlignment="Left"
                                    VerticalAlignment="Center"
                                    Margin="6"
                                    Grid.Row="0"
                                    Grid.Column="1"
                                    Filter="ExceptionTypeFilter"
                                    AllowNull="false"
                                    BrowseTypeDirectly="false"
                                    Label="Exception Type"
                                    Type="{Binding Path=ModelItem.ExceptionType, Mode=TwoWay, Converter={StaticResource ModelItemConverter}}"
                                    Context="{Binding Context}" />
            </Grid>
            <sap:WorkflowItemPresenter Item="{Binding ModelItem.Body.Handler}"
                                       HintText="Drop Activity"
                                       Margin="6" />
        </StackPanel>
    </DataTemplate>
    <Style x:Key="ExpandOrCollapsedStyle"
           TargetType="{x:Type ContentPresenter}">
        <Setter Property="ContentTemplate"
                Value="{DynamicResource Collapsed}" />
        <Style.Triggers>
            <DataTrigger Binding="{Binding Path=ShowExpanded}"
                         Value="true">
                <Setter Property="ContentTemplate"
                        Value="{DynamicResource Expanded}" />
            </DataTrigger>
        </Style.Triggers>
    </Style>
</sap:ActivityDesigner.Resources>
<Grid>
    <ContentPresenter Style="{DynamicResource ExpandOrCollapsedStyle}"
                      Content="{Binding}" Height="16" VerticalAlignment="Top" />
</Grid>

How can I debug this situation?

Thanks.


Solution

  • I resolved my issue by removing the Exception type as stated in comments and not having the icon graphic (using the default since it's not all that important.