Call Webservice without adding a WebReference - with Complex Types

Posted by ck on Stack Overflow See other posts from Stack Overflow or by ck
Published on 2010-04-12T12:32:11Z Indexed on 2010/04/12 15:43 UTC
Read the original article Hit count: 803

Filed under:
|

I'm using the code at This Site to call a webservice dynamically.

[SecurityPermissionAttribute(SecurityAction.Demand, Unrestricted = true)]
    public static object CallWebService(string webServiceAsmxUrl, string serviceName, string methodName, object[] args)
    {
        System.Net.WebClient client = new System.Net.WebClient();
        //-Connect To the web service
        using (System.IO.Stream stream = client.OpenRead(webServiceAsmxUrl + "?wsdl"))
        {
            //--Now read the WSDL file describing a service.
            ServiceDescription description = ServiceDescription.Read(stream);
            ///// LOAD THE DOM /////////
            //--Initialize a service description importer.
            ServiceDescriptionImporter importer = new ServiceDescriptionImporter();
            importer.ProtocolName = "Soap12"; // Use SOAP 1.2.
            importer.AddServiceDescription(description, null, null);
            //--Generate a proxy client. importer.Style = ServiceDescriptionImportStyle.Client;
            //--Generate properties to represent primitive values.
            importer.CodeGenerationOptions = System.Xml.Serialization.CodeGenerationOptions.GenerateProperties;
            //--Initialize a Code-DOM tree into which we will import the service.
            CodeNamespace nmspace = new CodeNamespace();
            CodeCompileUnit unit1 = new CodeCompileUnit();
            unit1.Namespaces.Add(nmspace);
            //--Import the service into the Code-DOM tree. This creates proxy code
            //--that uses the service.
            ServiceDescriptionImportWarnings warning = importer.Import(nmspace, unit1);
            if (warning == 0) //--If zero then we are good to go
            {
                //--Generate the proxy code 
                CodeDomProvider provider1 = CodeDomProvider.CreateProvider("CSharp");
                //--Compile the assembly proxy with the appropriate references
                string[] assemblyReferences = new string[5] { "System.dll", "System.Web.Services.dll", "System.Web.dll", "System.Xml.dll", "System.Data.dll" };
                CompilerParameters parms = new CompilerParameters(assemblyReferences);
                CompilerResults results = provider1.CompileAssemblyFromDom(parms, unit1);
                //-Check For Errors
                if (results.Errors.Count > 0)
                {
                    StringBuilder sb = new StringBuilder();
                    foreach (CompilerError oops in results.Errors)
                    {
                        sb.AppendLine("========Compiler error============");
                        sb.AppendLine(oops.ErrorText);
                    }
                    throw new System.ApplicationException("Compile Error Occured calling webservice. " + sb.ToString());
                }
                //--Finally, Invoke the web service method 
                Type foundType = null;
                Type[] types = results.CompiledAssembly.GetTypes();
                foreach (Type type in types)
                {
                    if (type.BaseType == typeof(System.Web.Services.Protocols.SoapHttpClientProtocol))
                    {
                        Console.WriteLine(type.ToString());
                        foundType = type;
                    }
                }

                object wsvcClass = results.CompiledAssembly.CreateInstance(foundType.ToString());
                MethodInfo mi = wsvcClass.GetType().GetMethod(methodName);
                return mi.Invoke(wsvcClass, args);
            }
            else
            {
                return null;
            }
        }
    }

This works fine when I use built in types, but for my own classes, I get this:

Event Type: Error
Event Source:   TDX Queue Service
Event Category: None
Event ID:   0
Date:       12/04/2010
Time:       12:12:38
User:       N/A
Computer:   TDXRMISDEV01
Description:
System.ArgumentException: Object of type 'TDXDataTypes.AgencyOutput' cannot be converted to type 'AgencyOutput'.

Server stack trace: 
   at System.RuntimeType.CheckValue(Object value, Binder binder, CultureInfo culture, BindingFlags invokeAttr)
   at System.Reflection.MethodBase.CheckArguments(Object[] parameters, Binder binder, BindingFlags invokeAttr, CultureInfo culture, Signature sig)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
   at TDXQueueEngine.GenericWebserviceProxy.CallWebService(String webServiceAsmxUrl, String serviceName, String methodName, Object[] args) in C:\CkAdmDev\TDXQueueEngine\TDXQueueEngine\TDXQueueEngine\GenericWebserviceProxy.cs:line 76
   at TDXQueueEngine.TDXQueueWebserviceItem.Run() in C:\CkAdmDev\TDXQueueEngine\TDXQueueEngine\TDXQueueEngine\TDXQueueWebserviceItem.cs:line 99
   at System.Runtime.Remoting.Messaging.StackBuilderSink._PrivateProcessMessage(IntPtr md, Object[] args, Object server, Int32 methodPtr, Boolean fExecuteInContext, Object[]& outArgs)
   at System.Runtime.Remoting.Messaging.StackBuilderSink.PrivateProcessMessage(RuntimeMethodHandle md, Object[] args, Object server, Int32 methodPtr, Boolean fExecuteInContext, Object[]& outArgs)
   at System.Runtime.Remoting.Messaging.StackBuilderSink.AsyncProcessMessage(IMessage msg, IMessageSink replySink)

Exception rethrown at [0]: 
   at System.Runtime.Remoting.Proxies.RealProxy.EndInvokeHelper(Message reqMsg, Boolean bProxyCase)
   at System.Runtime.Remoting.Proxies.RemotingProxy.Invoke(Object NotUsed, MessageData& msgData)
   at TDXQueueEngine.TDXQueue.RunProcess.EndInvoke(IAsyncResult result)
   at TDXQueueEngine.TDXQueue.processComplete(IAsyncResult ar) in C:\CkAdmDev\TDXQueueEngine\TDXQueueEngine\TDXQueueEngine\TDXQueue.cs:line 130

For more information, see Help and Support Center at http://go.microsoft.com/fwlink/events.asp.

The classes reference the same assembly and the same version. Do I need to include my assembly as a reference when building the temporary assembly? If so, how?

Thanks.

© Stack Overflow or respective owner

Related posts about c#

Related posts about web-services