Click here to Skip to main content
15,886,664 members
Articles / Desktop Programming / XAML

WF4 Custom activities for message mediation

Rate me:
Please Sign up or sign in to vote.
4.98/5 (25 votes)
20 Dec 2012CPOL24 min read 108.3K   2K   72  
This article describes a design, implementation, and usage of custom message mediation activities for a XAML workflow.
//*****************************************************************************
//    Description.....WF4 Message Mediation Library
//                                
//    Author..........Roman Kiss, rkiss@pathcom.com
//    Copyright © 2009 ATZ Consulting Inc. (see included license.rtf file)         
//                        
//    Date Created:    07/07/09
//
//    Date        Modified By     Description
//-----------------------------------------------------------------------------
//    07/07/09    Roman Kiss     Initial Revision
//
//*****************************************************************************
//
#region Namespaces
using System;
using System.Activities;
using System.Activities.Presentation.PropertyEditing;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.ServiceModel.Channels;
using System.Text;
using System.Windows.Markup;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Xsl;

#endregion

namespace RKiss.MessageMediationActivityLibrary
{
    [ContentProperty("Parameters")]
    public sealed class CreateMessage : CodeActivity
    {
        private IDictionary<string, InArgument> parameters;
   
        #region Properties    
        [Category("Input")]
        [RequiredArgument]
        [EditorBrowsable]
        [EditorReuse(false)]
        //[Editor(typeof(XmlValueExpressionEditor), typeof(PropertyValueEditor))]
        public InArgument<XElement> Mediator { get; set; }

        [Category("Input")]
        [Browsable(true)]
        [Editor(typeof(RKiss.MessageMediationActivityLibrary.Editors.DynamicArgumentDictionaryEditor), typeof(PropertyValueEditor))]
        public IDictionary<string, InArgument> Parameters
        {
            get
            {
                if (this.parameters == null)
                {
                    this.parameters = new Dictionary<string, InArgument>();
                }
                return this.parameters;
            }
        }

        [Category("Input")]
        [EditorBrowsable(EditorBrowsableState.Advanced)]
        [DefaultValue(MessageVersionOption.Default)]
        public MessageVersionOption MessageVersion { get; set; }

        [Category("Output")]
        [RequiredArgument]
        public OutArgument<Message> Message { get; set; }

        [Browsable(false)]
        public string SourceUri { get; set; }
        #endregion


        protected override void Execute(CodeActivityContext context)
        {
            XslCompiledTransform xsltprocessor = new XslCompiledTransform(false);
            XsltArgumentList xsltArgList = new XsltArgumentList();

            #region Step 1: Add functions to the XsltArgumentList
            // this feature was not implemented
            #endregion

            #region Step 2: Add parameters to the XsltArgumentList
            if (this.Parameters != null && this.Parameters.Count > 0)
            {
                foreach (var param in this.Parameters)
                {               
                    if (string.IsNullOrEmpty(param.Key) || param.Value == null || param.Value.Expression == null) continue;
                    XName xname = XName.Get(param.Key);
                    xsltArgList.AddParam(xname.LocalName, xname.NamespaceName, Convert.ToString(param.Value.Get(context)));
                }
            }
            #endregion

            #region Step 3: Load metadata
            try
            {
                using (MemoryStream msMetadata = new MemoryStream(UTF8Encoding.UTF8.GetBytes(this.Mediator.Get(context).ToString())))
                {
                    XmlDictionaryReader rdMetadata = XmlDictionaryReader.CreateTextReader(msMetadata, XmlDictionaryReaderQuotas.Max);
                    xsltprocessor.Load(rdMetadata);
                }
            }
            catch (Exception ex)
            {
                throw new Exception(string.Format("XslCompiledTransform loading in the activity '{0}' failed, error={1}", this.DisplayName, ex.Message), ex);
            }
            #endregion

            #region Step 4: Transform empty Input and create MessageOutput

            try
            {
                using (MemoryStream msMessageOutput = new MemoryStream())
                using (XmlDictionaryWriter wrMessageOutput = XmlDictionaryWriter.CreateTextWriter(msMessageOutput, Encoding.UTF8, true))
                using (XmlDictionaryReader rdEmptyInput = XmlDictionaryReader.CreateTextReader(UTF8Encoding.UTF8.GetBytes("<Root/>"), XmlDictionaryReaderQuotas.Max))
                {
                    xsltprocessor.Transform(rdEmptyInput, xsltArgList, wrMessageOutput);
                   
                    msMessageOutput.Position = 0;
                    XmlDictionaryReader rdMessageOutput = XmlDictionaryReader.CreateTextReader(msMessageOutput.ToArray(), XmlDictionaryReaderQuotas.Max);
                    Message outputMessage = System.ServiceModel.Channels.Message.CreateMessage(rdMessageOutput, int.MaxValue, LibHelper.MessageVersion(this.MessageVersion));
                    this.Message.Set(context, outputMessage);                
                }
            }
            catch (Exception ex)
            {
                throw new Exception(string.Format("Xslt transformation or creating an output message version '{0}' in the activity '{1}' failed", this.MessageVersion, this.DisplayName), ex);
            }
            #endregion
        }      
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions