2

The results from a rehosted designer (WF4) have an issue when adding a default value to an argument. Every other case seems to work fine. This is the (abridged) xaml of a (nearly) empty workflow.

<Activity mc:Ignorable="sap" x:Class="{x:Null}" this:_b40c.NewArg="test" xmlns="http://schemas.microsoft.com/netfx/2009/xaml/activities" 
xmlns:av="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
xmlns:mva="clr-namespace:Microsoft.VisualBasic.Activities;assembly=System.Activities" xmlns:sap="http://schemas.microsoft.com/netfx/2009/xaml/activities/presentation" 
xmlns:scg="clr-namespace:System.Collections.Generic;assembly=mscorlib" xmlns:this="clr-namespace:" xmlns:twc="clr-namespace:Telogis.Workflow.CustomerApi;assembly=Telogis.Workflow.Activities" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <x:Members>
    <x:Property Name="AuthenticationHeader" Type="InArgument(twc:AuthenticationHeader)" />
    <x:Property Name="BaseTdeUri" Type="InArgument(x:Uri)" />
    <x:Property Name="NewArg" Type="InArgument(x:String)" />
  </x:Members>
  <sap:VirtualizedContainerService.HintSize>654,676</sap:VirtualizedContainerService.HintSize>
  <mva:VisualBasic.Settings>Assembly references and imported namespaces serialized as XML namespaces</mva:VisualBasic.Settings>
  <Flowchart />
</Activity>

Specifically when default value is added, the following additions are made to the definition: this:_b40c.NewArg="test" and xmlns:this="clr-namespace:" xmlns:this="clr-namespace:" is invalid as it doesn't point anywhere and can't be parsed with ActivityXamlServices.Load(stream); (it throws XamlObjectWriterException: "'Cannot set unknown member '{clr-namespace:}_b40c.NewArg'.' ...) This seems to occur whatever the specified type of the argument is.

Any idea what could be causing this?

Update

I was using an ActivityBuilder to utilise the activity in the first place. This was fine, but as I hadn't provided it with a name, it had to generate a key, in the example above _b40c. ActivityXamlServices.Load has some kind off issue processing these keys. However, simply defining a name for ActivityBuilder seems to do the trick.

This still doesn't answer why it creates xmlns:this="clr-namespace:" without an actual namespace.

Hubris
  • 1,842
  • 2
  • 18
  • 26
  • 1
    Thanks for your solution with naming the ActivityBuilder! I had the same problem which in my opinion appeared recently with, I presume, Microsoft update. I've been using rehosted workflow designer (users of my application) for more than one year and everything worked fine with unnamed ActivityBuilder. Few weaks ago I got an issue that reholsted designer is not able to reload defined workflow if InArgument has default value defined. XAML was very similar to yours. Naming the ActivityBuilder did the trick! – zlakob May 28 '13 at 07:25
  • Thanks for the update - it definitely works :) I think you should write an answer to your own question and mark it as accepted - that would make your solution easier to find in the future. Thanks again! – Lasse Christiansen Jul 07 '16 at 05:36

2 Answers2

0

Your workflow xaml is invalid. I'm not sure where you got it or how it got into this state.

I can tell this because

<Activity 
    x:Class="{x:Null}" 
    this:_b40c.NewArg="test"
    xmlns:this="clr-namespace:" 

the clr-style namespace declaration is invalid. It should read

clr-namespace:Some.Namespace.In.The.Current.Assembly

or

clr-namespace:Some.Namespace;assembly=SomeAssemblyWithSomeNamespace

As your declaration is malformed, the this xml namespace cannot be parsed by the XamlObjectWriter in order to determine what namespace/assembly your _b40c type exists in. Also, that looks highly suspicious as well. And I've never seen an x:Class set to null before. That also strikes me as malformed.

  • I had figured out it was invalid, but I have no idea why the workflow designer would generate this output, especially when it generates valid xaml in all other cases. – Hubris Aug 09 '12 at 18:11
  • @Hubris: The answer lies in how you are rehosting. Which isn't in your question. –  Aug 09 '12 at 18:13
  • Sorry for not providing more details on the implementation and thank you very much for your help. – Hubris Aug 09 '12 at 20:27
0

If I understand well - this is WF Designer bug. I've faced with this problem when I had had to support default value definition for InArgument<T> in my custom WF designer. I still surprised lack of support for this basic procedure.

There are 2 reason of failure:

  1. Definition of {x:Null} in x:Class attribute
  2. Invalid definition of xmlns:this attribute
  3. And the main problem is invalid definition of Argument's default value: this:_effe.MyArgument="asd". The definition of default value for argument should be equal to this:MyXamlClassName.MyArgument="asd". For example, if your x:Cass definition is x:Class="MyNamespace.MyClass", Argument definition should be this:MyClass.MyArgument="asd".

I resolved it by intervention into XAML saving process: After calling of _workflowDesigner.Save(_editedFile);

I added these two lines:

     #region x:Class and Argument<T> default value issues solution

            await CreateAttributeValue(_editedFile, ConstXClassAttributeName, typeof(App).Namespace + "." + Path.GetFileNameWithoutExtension(_editedFile));
            //should finish first operation before second operation begins to avoid I/O exception
            await CreateAttributeValue(_editedFile, ConstNamespaceAttributeName, ConstXamlClrNamespace + typeof(App).Namespace);
            await RepairArgsAttributes(_editedFile);
                #endregion

This is the methods definition:


  /// <summary>
    /// Reason of using of this method: bug in workflow designer. When you save your xaml file, WF Designer assign "{x:Null}" to x:Class attribute
    /// Bug: In addition, if you want to set default value for your InArgument<T>, it defines attribute "this" (namespace declaration) with empty value. When you try to open your file, designer fails to parse XAML.
    /// </summary>
    /// <param name="editedFile"></param>
    /// <param name="attribteName"></param>
    /// <param name="attributeValueToReplace"></param>
    private static async Task CreateAttributeValue(string editedFile, string attribteName, string attributeValueToReplace)
    {
        XmlDocument xmlDoc = new XmlDocument();
        await Task.Run(() => xmlDoc.Load(editedFile));

        await Task.Run(() =>
        {
            var attributteToReplace = xmlDoc.FirstChild.Attributes?[attribteName];

            if (null != attributteToReplace)
            {
                xmlDoc.FirstChild.Attributes[attribteName].Value = attributeValueToReplace;
                xmlDoc.Save(editedFile);
            }
        });
    }

 /// <summary>
        /// Bug in Workflow designer: workflow designer saves declaration for In/Out Arguments in invalid format. Means, that it is unable to open the same file it saved itself. This method fixes the Arguments declaration in XAML xmlns
        /// </summary>
        /// <param name="editedFile"></param>
        /// <returns></returns>
        private async Task RepairArgsAttributes(string editedFile)
        {
            XmlDocument xmlDoc = new XmlDocument();
            await Task.Run(() => xmlDoc.Load(editedFile));

            await Task.Run(() =>
            {
                for (int i = 0; i < xmlDoc.FirstChild.Attributes.Count; i++)
                {
                    if (xmlDoc.FirstChild.Attributes[i].Name.StartsWith(ConstInvalidArgStarts))
                    {
                        string innvalidAttrName = xmlDoc.FirstChild.Attributes[i].Name;//extraction of full argument declaration in xmlns
                        string[] oldStrings = innvalidAttrName.Split('.');//extraction of arguemnt name string
                        string localName = Path.GetFileNameWithoutExtension(editedFile) + "." + oldStrings[1];//build valid argment declaration without perfix
                        string valueBackup = xmlDoc.FirstChild.Attributes[i].Value;//saving of default value of Arguemnt<T>
                        xmlDoc.FirstChild.Attributes.RemoveNamedItem(xmlDoc.FirstChild.Attributes[i].Name);//removal of invalid Arguemnt declaration with default value. WARNING: when you remove attribue, at this moment you have another item at the place xmlDoc.FirstChild.Attributes[i]
                        //definition of new valid attribute requries: set separelly attribute prefix, localName (not "name" - it causes invalid attribute definition) and valid namespace url (in our case it's namespace deifinition in "this")
                        XmlAttribute attr = xmlDoc.CreateAttribute(ConstArgPrefix, localName, xmlDoc.FirstChild.Attributes[ConstNamespaceAttributeName].Value);
                        attr.Value = valueBackup;
                        xmlDoc.FirstChild.Attributes.InsertBefore(attr, xmlDoc.FirstChild.Attributes[i]);//define new correct Argument declaration attribute at the same place where was invalid attribute. When you put valid attribute at the same place your recover valid order of attributes that was changed while removal of invalid attribute declaration
                    }
                }
                xmlDoc.Save(editedFile);

            });
        }

The constants definition are:

 #region Constants
    private const string ConstXClassAttributeName = "x:Class";
    private const string ConstXamlClrNamespace = "clr-namespace:";
    private const string ConstNamespaceAttributeName = "xmlns:this";
    private const string ConstInvalidArgStarts = @"this:_";
    private const string ConstArgPrefix = @"this";

    #endregion

This solution should resolve your issue too.

Mr.B
  • 3,484
  • 2
  • 26
  • 40