File: InvokeWebService.cs
Project: ndp\cdf\src\WF\Activities\System.Workflow.Activities.csproj (System.Workflow.Activities)
namespace System.Workflow.Activities
{
    #region Imports
 
    using System;
    using System.Text;
    using System.Reflection;
    using System.Collections;
    using System.CodeDom;
    using System.ComponentModel;
    using System.ComponentModel.Design;
    using System.Drawing.Design;
    using System.Drawing;
    using System.Windows.Forms;
    using System.Workflow.ComponentModel;
    using System.Workflow.ComponentModel.Design;
    using System.Runtime.Serialization;
    using System.Workflow.ComponentModel.Compiler;
    using System.ComponentModel.Design.Serialization;
    using System.Collections.Specialized;
    using System.Xml;
    using System.Web.Services.Protocols;
    using System.Collections.Generic;
    using System.Workflow.Runtime;
    using System.Workflow.Activities.Common;
    #endregion
 
    #region Class InvokeWebService
 
    [Serializable]
    [Obsolete("The System.Workflow.* types are deprecated.  Instead, please use the new types from System.Activities.*")]
    public sealed class InvokeWebServiceEventArgs : EventArgs
    {
        [NonSerialized]
        Object proxyInstance;
 
        public InvokeWebServiceEventArgs(Object proxyInstance)
        {
            this.proxyInstance = proxyInstance;
        }
 
        public Object WebServiceProxy
        {
            get
            {
                return this.proxyInstance;
            }
        }
    }
 
    [SRDescription(SR.InvokeWebServiceActivityDescription)]
    [ToolboxItem(typeof(InvokeWebServiceToolboxItem))]
    [Designer(typeof(InvokeWebServiceDesigner), typeof(IDesigner))]
    [ToolboxBitmap(typeof(InvokeWebServiceActivity), "Resources.WebServiceInOut.png")]
    [ActivityValidator(typeof(InvokeWebServiceValidator))]
    [SRCategory(SR.Standard)]
    [Obsolete("The System.Workflow.* types are deprecated.  Instead, please use the new types from System.Activities.*")]
    public sealed class InvokeWebServiceActivity : Activity, IPropertyValueProvider, IDynamicPropertyTypeProvider
    {
        private static readonly Guid WebServiceInvoker = new Guid("C3FE5ABC-7D41-4064-810E-42BEF0A855EC");
 
        public static readonly DependencyProperty ProxyClassProperty = DependencyProperty.Register("ProxyClass", typeof(Type), typeof(InvokeWebServiceActivity), new PropertyMetadata(null, DependencyPropertyOptions.Metadata));
        public static readonly DependencyProperty MethodNameProperty = DependencyProperty.Register("MethodName", typeof(string), typeof(InvokeWebServiceActivity), new PropertyMetadata("", DependencyPropertyOptions.Metadata));
        public static readonly DependencyProperty SessionIdProperty = DependencyProperty.Register("SessionId", typeof(string), typeof(InvokeWebServiceActivity), new PropertyMetadata("", DependencyPropertyOptions.Metadata));
        public static readonly DependencyProperty ParameterBindingsProperty = DependencyProperty.Register("ParameterBindings", typeof(WorkflowParameterBindingCollection), typeof(InvokeWebServiceActivity), new PropertyMetadata(DependencyPropertyOptions.Metadata | DependencyPropertyOptions.ReadOnly, new Attribute[] { new BrowsableAttribute(false), new DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Content) }));
        public static readonly DependencyProperty InvokingEvent = DependencyProperty.Register("Invoking", typeof(EventHandler<InvokeWebServiceEventArgs>), typeof(InvokeWebServiceActivity));
        public static readonly DependencyProperty InvokedEvent = DependencyProperty.Register("Invoked", typeof(EventHandler<InvokeWebServiceEventArgs>), typeof(InvokeWebServiceActivity));
 
        static DependencyProperty SessionCookieContainerProperty = DependencyProperty.Register("SessionCookieContainer", typeof(System.Net.CookieContainer), typeof(InvokeWebServiceActivity));
        static DependencyProperty SessionCookieMapProperty = DependencyProperty.RegisterAttached("SessionCookieMap", typeof(Dictionary<String, System.Net.CookieContainer>), typeof(InvokeWebServiceActivity));
 
        #region Constructors
 
        public InvokeWebServiceActivity()
        {
            base.SetReadOnlyPropertyValue(ParameterBindingsProperty, new WorkflowParameterBindingCollection(this));
        }
 
        public InvokeWebServiceActivity(string name)
            : base(name)
        {
            base.SetReadOnlyPropertyValue(ParameterBindingsProperty, new WorkflowParameterBindingCollection(this));
        }
 
        #endregion
 
        internal System.Net.CookieContainer SessionCookieContainer
        {
            get
            {
                return (System.Net.CookieContainer)base.GetValue(SessionCookieContainerProperty);
            }
            set
            {
                base.SetValue(SessionCookieContainerProperty, value);
            }
        }
 
        internal static readonly ArrayList ReservedParameterNames = new ArrayList(new string[] { "Name", "Enabled", "Description", "MethodName", "ProxyClass", "SessionId", "Invoked", "Invoking" });
 
        #region Execute()
 
        protected override sealed ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
        {
            if (executionContext == null)
                throw new ArgumentNullException("executionContext");
 
            if (SessionId != "" && SessionId != null)
                PopulateSessionCookie();
 
 
            // Create instance of Proxy.
            object proxyInstance = Activator.CreateInstance(this.ProxyClass);
 
            //Set Session Cookie
            System.Web.Services.Protocols.HttpWebClientProtocol proxy = proxyInstance as System.Web.Services.Protocols.HttpWebClientProtocol;
            System.Diagnostics.Debug.Assert(proxy != null);
            proxy.CookieContainer = this.SessionCookieContainer;
 
            //Invoke OnBefore Invoke
            this.RaiseGenericEvent(InvokeWebServiceActivity.InvokingEvent, this, new InvokeWebServiceEventArgs(proxyInstance));
 
            // Get the parameters.
            MethodInfo methodInfo = this.ProxyClass.GetMethod(this.MethodName, BindingFlags.Instance | BindingFlags.Public);
 
            object[] actualParameters = InvokeHelper.GetParameters(methodInfo, this.ParameterBindings);
 
            WorkflowParameterBinding resultBinding = null;
 
            if (this.ParameterBindings.Contains("(ReturnValue)"))
                resultBinding = this.ParameterBindings["(ReturnValue)"];
 
            Object result = null;
 
            try
            {
                //Invoke the Web Service.
                result = this.ProxyClass.InvokeMember(this.MethodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.InvokeMethod, null, proxyInstance, actualParameters, System.Globalization.CultureInfo.InvariantCulture);
            }
            catch (TargetInvocationException e)
            {
                if (e.InnerException != null)
                    throw e.InnerException;
                else
                    throw;
            }
 
            // Save the result.
            if (resultBinding != null)
                resultBinding.Value = result;
 
            // Save ref parameters.
            InvokeHelper.SaveOutRefParameters(actualParameters, methodInfo, this.ParameterBindings);
 
            //Invoke OnAfter Invoke
            this.RaiseGenericEvent(InvokeWebServiceActivity.InvokedEvent, this, new InvokeWebServiceEventArgs(proxyInstance));
 
            return ActivityExecutionStatus.Closed;
        }
 
        void PopulateSessionCookie()
        {
            //Already session cookie is populated.
            if (this.SessionCookieContainer != null)
                return;
 
            //Map of Session - CookieContainer is populated in RootActvity.
            Activity rootActivity = (Activity)GetRootActivity();
            Dictionary<String, System.Net.CookieContainer> sessionCookieContainers;
            System.Net.CookieContainer cookieContainer;
 
            sessionCookieContainers = (Dictionary<String, System.Net.CookieContainer>)rootActivity.GetValue(SessionCookieMapProperty);
 
            if (sessionCookieContainers == null)
            {
                sessionCookieContainers = new Dictionary<String, System.Net.CookieContainer>();
                rootActivity.SetValue(SessionCookieMapProperty, sessionCookieContainers);
                cookieContainer = new System.Net.CookieContainer();
                sessionCookieContainers.Add(SessionId, cookieContainer);
            }
            else
            {
                if (!sessionCookieContainers.TryGetValue(SessionId, out cookieContainer))
                {
                    cookieContainer = new System.Net.CookieContainer();
                    sessionCookieContainers.Add(SessionId, cookieContainer);
                }
            }
            this.SessionCookieContainer = cookieContainer;
        }
 
        Activity GetRootActivity()
        {
            Activity parent = this;
 
            while (true)
            {
                if (parent.Parent == null)
                    return parent;
 
                parent = parent.Parent;
            }
        }
 
        protected override void OnClosed(IServiceProvider provider)
        {
            base.RemoveProperty(InvokeWebServiceActivity.SessionCookieContainerProperty);
            base.RemoveProperty(InvokeWebServiceActivity.SessionCookieMapProperty);
        }
 
        #endregion
 
        [SRCategory(SR.Activity)]
        [SRDescription(SR.ProxyClassDescr)]
        [TypeConverter(typeof(TypePropertyValueProviderTypeConverter))]
        [RefreshProperties(RefreshProperties.All)]
        [MergablePropertyAttribute(false)]
        [DefaultValue(null)]
        public Type ProxyClass
        {
            get
            {
                return base.GetValue(ProxyClassProperty) as Type;
            }
            set
            {
                base.SetValue(ProxyClassProperty, value);
            }
        }
        [RefreshProperties(RefreshProperties.All)]
        [TypeConverter(typeof(PropertyValueProviderTypeConverter))]
        [SRCategory(SR.Activity)]
        [SRDescription(SR.MethodNameDescr)]
        [MergablePropertyAttribute(false)]
        [DefaultValue("")]
        public string MethodName
        {
            get
            {
                return base.GetValue(MethodNameProperty) as string;
            }
            set
            {
                base.SetValue(MethodNameProperty, value);
            }
        }
 
 
 
        [SRCategory(SR.Handlers)]
        [SRDescription(SR.OnBeforeMethodInvokeDescr)]
        [MergableProperty(false)]
        public event EventHandler<InvokeWebServiceEventArgs> Invoking
        {
            add
            {
                base.AddHandler(InvokingEvent, value);
            }
            remove
            {
                base.RemoveHandler(InvokingEvent, value);
            }
        }
 
        [SRCategory(SR.Handlers)]
        [SRDescription(SR.OnAfterMethodInvokeDescr)]
        [MergableProperty(false)]
        public event EventHandler<InvokeWebServiceEventArgs> Invoked
        {
            add
            {
                base.AddHandler(InvokedEvent, value);
            }
            remove
            {
                base.RemoveHandler(InvokedEvent, value);
            }
        }
 
 
        [SRCategory(SR.Activity)]
        [SRDescription(SR.WebServiceSessionIDDescr)]
        [DefaultValue("")]
        [MergablePropertyAttribute(false)]
        public string SessionId
        {
            get
            {
                return base.GetValue(SessionIdProperty) as string;
            }
            set
            {
                base.SetValue(SessionIdProperty, value);
            }
        }
 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        [Browsable(false)]
        public WorkflowParameterBindingCollection ParameterBindings
        {
            get
            {
                return base.GetValue(ParameterBindingsProperty) as WorkflowParameterBindingCollection;
            }
        }
 
        #region IPropertyValueProvider Members
 
        ICollection IPropertyValueProvider.GetPropertyValues(ITypeDescriptorContext context)
        {
            ITypeProvider typeProvider = (ITypeProvider)context.GetService(typeof(ITypeProvider));
            if (typeProvider == null)
                throw new InvalidOperationException(SR.GetString(SR.General_MissingService, typeof(ITypeProvider).FullName));
 
            ICollection values = null;
            if (context.PropertyDescriptor.Name == "ProxyClass")
            {
                List<Type> typeList = new List<Type>();
                Type webServiceBaseType = typeProvider.GetType(typeof(System.Web.Services.Protocols.SoapHttpClientProtocol).FullName);
                if (webServiceBaseType != null)
                {
                    Type[] types = typeProvider.GetTypes();
                    foreach (Type type in types)
                    {
                        if (!(type.Equals(webServiceBaseType)) && TypeProvider.IsAssignable(webServiceBaseType, type))
                            typeList.Add(type);
                    }
                }
                values = typeList.ToArray();
            }
            else if (context.PropertyDescriptor.Name == "MethodName")
            {
                StringCollection names = new StringCollection();
                Type type = this.ProxyClass;
                if (type != null)
                {
                    foreach (MethodInfo method in type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public))
                    {
                        object[] attrs = method.GetCustomAttributes(typeof(SoapDocumentMethodAttribute), false);
                        if (attrs == null || attrs.Length == 0)
                            attrs = method.GetCustomAttributes(typeof(SoapRpcMethodAttribute), false);
                        if (attrs != null && attrs.Length > 0)
                            names.Add(method.Name);
                    }
                }
                values = names;
            }
            return values;
        }
 
        #endregion
 
        #region IDynamicPropertyTypeProvider
 
        Type IDynamicPropertyTypeProvider.GetPropertyType(IServiceProvider serviceProvider, string propertyName)
        {
            if (propertyName == null)
                throw new ArgumentNullException("propertyName");
 
            Dictionary<string, object> parameters = new Dictionary<string, object>();
            this.GetParameterPropertyDescriptors(parameters);
            if (parameters.ContainsKey(propertyName))
            {
                ParameterInfoBasedPropertyDescriptor descriptor = parameters[propertyName] as ParameterInfoBasedPropertyDescriptor;
                if (descriptor != null)
                    return descriptor.ParameterType;
            }
 
            return null;
        }
 
        AccessTypes IDynamicPropertyTypeProvider.GetAccessType(IServiceProvider serviceProvider, string propertyName)
        {
            if (propertyName == null)
                throw new ArgumentNullException("propertyName");
 
            return AccessTypes.Read;
        }
 
        internal void GetParameterPropertyDescriptors(IDictionary properties)
        {
            if (((IComponent)this).Site == null)
                return;
 
            ITypeProvider typeProvider = (ITypeProvider)((IComponent)this).Site.GetService(typeof(ITypeProvider));
            if (typeProvider == null)
                throw new InvalidOperationException(SR.GetString(SR.General_MissingService, typeof(ITypeProvider).FullName));
 
            Type type = this.ProxyClass;
            if (type != null)
            {
                MethodInfo method = type.GetMethod(this.MethodName);
                if (method != null)
                {
                    ArrayList paramInfos = new ArrayList(method.GetParameters());
                    if (!(method.ReturnType == typeof(void)))
                        paramInfos.Add(method.ReturnParameter);
 
                    foreach (ParameterInfo paramInfo in paramInfos)
                    {
                        if (paramInfo.ParameterType != null)
                        {
                            PropertyDescriptor prop = null;
                            if (paramInfo.Position == -1)
                                prop = new ParameterInfoBasedPropertyDescriptor(typeof(InvokeWebServiceActivity), paramInfo, false, DesignOnlyAttribute.Yes);
                            else
                                prop = new ParameterInfoBasedPropertyDescriptor(typeof(InvokeWebServiceActivity), paramInfo, InvokeWebServiceActivity.ReservedParameterNames.Contains(paramInfo.Name), DesignOnlyAttribute.Yes);
 
                            // return this parameter
                            properties[prop.Name] = prop;
                        }
                    }
                }
            }
        }
        #endregion
 
    }
    #endregion
 
    #region class InvokeWebServiceValidator
 
    internal sealed class InvokeWebServiceValidator : ActivityValidator
    {
        public override ValidationErrorCollection Validate(ValidationManager manager, object obj)
        {
            ValidationErrorCollection validationErrors = base.Validate(manager, obj);
 
            InvokeWebServiceActivity invokeWebService = obj as InvokeWebServiceActivity;
            if (invokeWebService == null)
                throw new ArgumentException(SR.GetString(SR.Error_UnexpectedArgumentType, typeof(InvokeWebServiceActivity).FullName), "obj");
 
            if (invokeWebService.ProxyClass == null)
            {
                ValidationError error = new ValidationError(SR.GetString(SR.Error_TypePropertyInvalid, "ProxyClass"), ErrorNumbers.Error_PropertyNotSet);
                error.PropertyName = "ProxyClass";
                validationErrors.Add(error);
            }
            else
            {
                ITypeProvider typeProvider = (ITypeProvider)manager.GetService(typeof(ITypeProvider));
                if (typeProvider == null)
                    throw new InvalidOperationException(SR.GetString(SR.General_MissingService, typeof(ITypeProvider).FullName));
 
                Type proxyClassType = invokeWebService.ProxyClass;
 
                // Validate method
                if (invokeWebService.MethodName == null || invokeWebService.MethodName.Length == 0)
                    validationErrors.Add(ValidationError.GetNotSetValidationError("MethodName"));
                else
                {
                    MethodInfo methodInfo = proxyClassType.GetMethod(invokeWebService.MethodName);
                    if (methodInfo == null)
                    {
                        ValidationError error = new ValidationError(SR.GetString(SR.Error_MethodNotExists, "MethodName", invokeWebService.MethodName), ErrorNumbers.Error_MethodNotExists);
                        error.PropertyName = "MethodName";
                        validationErrors.Add(error);
                    }
                    else
                    {
                        ArrayList paramInfos = new ArrayList(methodInfo.GetParameters());
                        if (methodInfo.ReturnType != typeof(void))
                            paramInfos.Add(methodInfo.ReturnParameter);
 
                        foreach (ParameterInfo paramInfo in paramInfos)
                        {
                            string paramName = paramInfo.Name;
                            if (paramInfo.Position == -1)
                                paramName = "(ReturnValue)";
 
                            object paramValue = null;
                            if (invokeWebService.ParameterBindings.Contains(paramName))
                            {
                                if (invokeWebService.ParameterBindings[paramName].IsBindingSet(WorkflowParameterBinding.ValueProperty))
                                    paramValue = invokeWebService.ParameterBindings[paramName].GetBinding(WorkflowParameterBinding.ValueProperty);
                                else
                                    paramValue = invokeWebService.ParameterBindings[paramName].GetValue(WorkflowParameterBinding.ValueProperty);
                            }
                            if (!invokeWebService.ParameterBindings.Contains(paramName) || paramValue == null)
                            {
                                ValidationError validationError = ValidationError.GetNotSetValidationError(paramName);
                                if (InvokeWebServiceActivity.ReservedParameterNames.Contains(paramName))
                                    validationError.PropertyName = ParameterInfoBasedPropertyDescriptor.GetParameterPropertyName(invokeWebService.GetType(), paramName);
                                validationError.PropertyName = paramName;
                                validationErrors.Add(validationError);
                            }
                            else
                            {
                                AccessTypes access = AccessTypes.Read;
                                if (paramInfo.IsOut || paramInfo.IsRetval)
                                    access = AccessTypes.Write;
                                else if (paramInfo.ParameterType.IsByRef)
                                    access |= AccessTypes.Write;
 
                                ValidationErrorCollection variableErrors = ValidationHelpers.ValidateProperty(manager, invokeWebService, paramValue,
                                                                                new PropertyValidationContext(invokeWebService.ParameterBindings[paramName], null, paramName), new BindValidationContext(paramInfo.ParameterType.IsByRef ? paramInfo.ParameterType.GetElementType() : paramInfo.ParameterType, access));
                                if (InvokeWebServiceActivity.ReservedParameterNames.Contains(paramName))
                                {
                                    foreach (ValidationError validationError in variableErrors)
                                        validationError.PropertyName = ParameterInfoBasedPropertyDescriptor.GetParameterPropertyName(invokeWebService.GetType(), paramName);
                                }
                                validationErrors.AddRange(variableErrors);
                            }
                        }
 
                        if (invokeWebService.ParameterBindings.Count > paramInfos.Count)
                            validationErrors.Add(new ValidationError(SR.GetString(SR.Warning_AdditionalBindingsFound), ErrorNumbers.Warning_AdditionalBindingsFound, true));
                    }
                }
            }
            return validationErrors;
        }
    }
 
    #endregion
}