C# – Dynamically Invoke Web Service At Runtime

Web services have become an integral part of the communications between software over a network. There are a lot of ugly details behind how they work but thankfully C# hide a lot of those gory details. What you need to know is that there is a web service description (WSDL) that describes the available services and the data types they use (via XML).

You can use the WSDL to create types in C# that can communicate with the web service. There are a couple of ways that you can do this. You can generate a proxy class using the WSDL utility in the .NET SDK and add it to your project. You can also download the WSDL file at runtime, create the proxy class, compile it into an assembly, and execute the methods on it. This allows you to dynamically invoke methods from a web service that aren’t known at build time and is the approach I will explore today.

Step 1 – Obtain a ServiceDescriptionImporter

We want to create a ServiceDescriptionImporter object that we can use to generate the web service proxy class. We have to pass to it the WSDL location which is an XML document.

XmlTextReader xmlreader = new XmlTextReader(“MyWebService” + "?wsdl");
 
ServiceDescription serviceDescription = ServiceDescription.Read(xmlreader);
 
// build an importer, that assumes the SOAP protocol, client binding, and generates properties
ServiceDescriptionImporter descriptionImporter = new ServiceDescriptionImporter();
descriptionImporter.ProtocolName = "Soap";
descriptionImporter.AddServiceDescription(serviceDescription, null, null);
descriptionImporter.Style = ServiceDescriptionImportStyle.Client;
descriptionImporter.CodeGenerationOptions = System.Xml.Serialization.CodeGenerationOptions.GenerateProperties;

Step 2 – Compile an Assembly from the importer

Now that we have the ServiceDescriptionImporter we need to use it to compile a proxy assembly that we can use to communicate with the web service. The assembly will exist in the users’ temporary folder.

// a namespace and compile unit are needed by importer
CodeNamespace codeNamespace = new CodeNamespace();
CodeCompileUnit codeUnit = new CodeCompileUnit();
 
codeUnit.Namespaces.Add(codeNamespace);
 
ServiceDescriptionImportWarnings importWarnings = descriptionImporter.Import(codeNamespace, codeUnit);
 
if (importWarnings == 0) // no warnings
{
     // create a c# compiler
     CodeDomProvider compiler = CodeDomProvider.CreateProvider("CSharp");
 
     // include the assembly references needed to compile
     string[] references = new string[2] { "System.Web.Services.dll", "System.Xml.dll" };
 
     CompilerParameters parameters = new CompilerParameters(references);
 
     // compile into assembly
     CompilerResults results = compiler.CompileAssemblyFromDom(parameters, codeUnit);
 
     foreach (CompilerError oops in results.Errors)
     {
          // trap these errors and make them available to exception object
          throw new Exception("Compilation Error Creating Assembly");
     }
 
     // all done....
     return results.CompiledAssembly;
}
else
{
     // warnings issued from importers, something wrong with WSDL
     throw new Exception("Invalid WSDL");
}

Step 3 – Execute Methods from the Web Service

Finally we have an assembly built from the web service description and now we can invoke methods from it just like any other ordinary assembly we might use. To accomplish this we must use reflection to discover the correct method.

object obj = this.webServiceAssembly.CreateInstance(serviceName);
 
Type type = obj.GetType();
 
return (T)type.InvokeMember(methodName, BindingFlags.InvokeMethod, null, obj, args);

And there you have it, dynamic invocation of web service methods at runtime. Using this technique you can invoke methods from any arbitrary web service at runtime.

Here is a full example class for dynamically invoking a web service method in C#.

using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Web.Services;
using System.Web.Services.Description;
using System.Web.Services.Discovery;
using System.Xml;
 
namespace DynamicWebExample
{
    class WebServiceInvoker
    {
        Dictionary<string, Type> availableTypes;
 
        /// <summary>
        /// Text description of the available services within this web service.
        /// </summary>
        public List<string> AvailableServices
        {
            get{ return this.services; }
        }
 
        /// <summary>
        /// Creates the service invoker using the specified web service.
        /// </summary>
        /// <param name="webServiceUri"></param>
        public WebServiceInvoker(Uri webServiceUri)
        {
            this.services = new List<string>(); // available services
            this.availableTypes = new Dictionary<string, Type>(); // available types
 
            // create an assembly from the web service description
            this.webServiceAssembly = BuildAssemblyFromWSDL(webServiceUri);
 
            // see what service types are available
            Type[] types = this.webServiceAssembly.GetExportedTypes();
 
            // and save them
            foreach (Type type in types)
            {
                services.Add(type.FullName);
                availableTypes.Add(type.FullName, type);
            }
        }
 
        /// <summary>
        /// Gets a list of all methods available for the specified service.
        /// </summary>
        /// <param name="serviceName"></param>
        /// <returns></returns>
        public List<string> EnumerateServiceMethods(string serviceName)
        {
            List<string> methods = new List<string>();
 
            if (!this.availableTypes.ContainsKey(serviceName))
                throw new Exception("Service Not Available");
            else
            {
                Type type = this.availableTypes[serviceName];
 
                // only find methods of this object type (the one we generated)
                // we don't want inherited members (this type inherited from SoapHttpClientProtocol)
                foreach (MethodInfo minfo in type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly))
                    methods.Add(minfo.Name);
 
                return methods;
            }
        }
 
        /// <summary>
        /// Invokes the specified method of the named service.
        /// </summary>
        /// <typeparam name="T">The expected return type.</typeparam>
        /// <param name="serviceName">The name of the service to use.</param>
        /// <param name="methodName">The name of the method to call.</param>
        /// <param name="args">The arguments to the method.</param>
        /// <returns>The return value from the web service method.</returns>
        public T InvokeMethod<T>( string serviceName, string methodName, params object[] args )
        {
            // create an instance of the specified service
            // and invoke the method
            object obj = this.webServiceAssembly.CreateInstance(serviceName);
 
            Type type = obj.GetType();
 
            return (T)type.InvokeMember(methodName, BindingFlags.InvokeMethod, null, obj, args);
        }
 
        /// <summary>
        /// Builds the web service description importer, which allows us to generate a proxy class based on the 
        /// content of the WSDL described by the XmlTextReader.
        /// </summary>
        /// <param name="xmlreader">The WSDL content, described by XML.</param>
        /// <returns>A ServiceDescriptionImporter that can be used to create a proxy class.</returns>
        private ServiceDescriptionImporter BuildServiceDescriptionImporter( XmlTextReader xmlreader )
        {
            // make sure xml describes a valid wsdl
            if (!ServiceDescription.CanRead(xmlreader))
                throw new Exception("Invalid Web Service Description");
 
            // parse wsdl
            ServiceDescription serviceDescription = ServiceDescription.Read(xmlreader);
 
            // build an importer, that assumes the SOAP protocol, client binding, and generates properties
            ServiceDescriptionImporter descriptionImporter = new ServiceDescriptionImporter();
            descriptionImporter.ProtocolName = "Soap";
            descriptionImporter.AddServiceDescription(serviceDescription, null, null);
            descriptionImporter.Style = ServiceDescriptionImportStyle.Client;
            descriptionImporter.CodeGenerationOptions = System.Xml.Serialization.CodeGenerationOptions.GenerateProperties;
 
            return descriptionImporter;
        }
 
        /// <summary>
        /// Compiles an assembly from the proxy class provided by the ServiceDescriptionImporter.
        /// </summary>
        /// <param name="descriptionImporter"></param>
        /// <returns>An assembly that can be used to execute the web service methods.</returns>
        private Assembly CompileAssembly(ServiceDescriptionImporter descriptionImporter)
        {
            // a namespace and compile unit are needed by importer
            CodeNamespace codeNamespace = new CodeNamespace();
            CodeCompileUnit codeUnit = new CodeCompileUnit();
 
            codeUnit.Namespaces.Add(codeNamespace);
 
            ServiceDescriptionImportWarnings importWarnings = descriptionImporter.Import(codeNamespace, codeUnit);
 
            if (importWarnings == 0) // no warnings
            {
                // create a c# compiler
                CodeDomProvider compiler = CodeDomProvider.CreateProvider("CSharp");
 
                // include the assembly references needed to compile
                string[] references = new string[2] { "System.Web.Services.dll", "System.Xml.dll" };
 
                CompilerParameters parameters = new CompilerParameters(references);
 
                // compile into assembly
                CompilerResults results = compiler.CompileAssemblyFromDom(parameters, codeUnit);
 
                foreach (CompilerError oops in results.Errors)
                {
                    // trap these errors and make them available to exception object
                    throw new Exception("Compilation Error Creating Assembly");
                }
 
                // all done....
                return results.CompiledAssembly;
            }
            else
            {
                // warnings issued from importers, something wrong with WSDL
                throw new Exception("Invalid WSDL");
            }
        }
 
        /// <summary>
        /// Builds an assembly from a web service description.
        /// The assembly can be used to execute the web service methods.
        /// </summary>
        /// <param name="webServiceUri">Location of WSDL.</param>
        /// <returns>A web service assembly.</returns>
        private Assembly BuildAssemblyFromWSDL(Uri webServiceUri)
        {
            if (String.IsNullOrEmpty(webServiceUri.ToString()))
                throw new Exception("Web Service Not Found");
 
            XmlTextReader xmlreader = new XmlTextReader(webServiceUri.ToString() + "?wsdl");
 
            ServiceDescriptionImporter descriptionImporter = BuildServiceDescriptionImporter(xmlreader);
 
            return CompileAssembly(descriptionImporter);
        }
 
        private Assembly webServiceAssembly;
        private List<string> services;
    }
}

This C# class can be easily used to invoke web service methods:

WebServiceInvoker invoker = new WebServiceInvoker(new Uri("http://localhost/services/test.php"));
 
string service = “MyService”;
string method = “MyMethod”;
 
string[] args = new string[] { “arg1”, “arg2” };
 
string result = invoker.InvokeMethod<string>(service, method, args);

I’ve put together an example application that you can download to evaluate the class. It allows you to invoke methods from a web service entered on the GUI and see the return value. You can download it here.

I hope you find this useful and if you have any questions or comments be sure to leave them here.

April 8, 2009 · crow · 90 Comments
Posted in: Programming

90 Responses

  1. Joel Chinchilla - April 17, 2009

    Hi, I tried to test your example with a Java Web Service, however I need to pass credentials to Web Service. How can I do it?

  2. Neena - May 7, 2009

    Can I call this code from java

  3. crow - May 10, 2009

    Not that I am aware of.

  4. Sergio - May 14, 2009

    Hi!
    finally a good example on how to call WS dynamically!
    I tryed your code, and got this problem:
    - my WS is as follows:

    public class Service1 : System.Web.Services.WebService
    {
    public Service1()
    {
    InitializeComponent();
    }

    [WebMethod]
    public double Sum(double num1, double num2)
    {
    if ( guid == “”)
    return -1;
    return num1 + num2;
    }
    }

    couldn’t be as simpler as this.
    When i run your code, it does in fact create an assemby whith the correct Service1 classname and the Sum method.
    So everything seems to be ok.
    Problem is when I invoke Sum method it sends an exception saying that “Method ‘Service1.Sum’ not found” on line :
    return (T)type.InvokeMember(methodName, BindingFlags.InvokeMethod, null, obj, args);

    Any clue?

    thanks in advance!

  5. shortcuts - May 18, 2009

    Off-topic Help – Need a secure web proxy to get around my school firewall. Any suggestions?

  6. Jeremy Foster - May 19, 2009

    I have this implemented and working but I have run into a limitation. I can not figure out how to capture multiple returned values in the SOAP response. Do you know of a way to do this?

  7. Sergio - May 19, 2009

    Jeremy,

    what do you mean with “multiple returned values in the SOAP response”. A method only returns 1 value/object. The value itself can have a collection of values/objects. Is this what you meant?
    You may try to transform the returned value to XML. Use this:

    public static string SerializeObjectToXML(T obj)
    {
    try
    {
    string xmlString = null;
    MemoryStream memoryStream = new MemoryStream();
    System.Xml.Serialization.XmlSerializer xs = new System.Xml.Serialization.XmlSerializer(typeof(T));
    string s = “”;
    XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8);
    System.Runtime.Serialization.Formatters.Soap.SoapFormatter xsoap = new System.Runtime.Serialization.Formatters.Soap.SoapFormatter();
    xsoap.Serialize(memoryStream, obj);

    xmlString = UTF8ByteArrayToString(memoryStream.ToArray());
    return xmlString;
    }
    catch(Exception ex)
    {
    ex.GetType();
    return string.Empty;
    }
    }

    public static T UnserializeObjectFromXML(string xml)
    {
    System.Xml.Serialization.XmlSerializer xs = new System.Xml.Serialization.XmlSerializer(typeof(T));
    MemoryStream memoryStream = new MemoryStream(StringToUTF8ByteArray(xml));
    XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8);
    return (T)xs.Deserialize(memoryStream);
    }

    The Serialize method uses the SoapFormatter class, and in fact serializes the returned object just like what the Webservice call does.

  8. Izzy - May 22, 2009

    Hi, Crows.
    i get this webpage/artical by google.

    i got one question.

    if the input parameter of the method is normal types, like string, int etc, then it is ok.

    right now, I got one webservie, and its input parameter of the function is like this

    string
    string
    int
    int
    int
    int
    int
    int
    int
    int

    there is only one input parameter : TestMessage_input.
    it is a type which is similiar with Struct.

    I’m confused about how to forming such an input parameter in GUI???
    thanks

    your reply will be appreciated and helpful.

  9. Izzy - May 22, 2009

    oh,some infos are missing.they were deleted automatically.

    would you mind telling me your email?
    since i really have some confusions about using this.
    is that ok?

  10. Shaun - May 22, 2009

    Excellent routine! I’m having a problem using this class however. When I call “return results.CompiledAssembly;” I get the following exception:

    Execution permission cannot be acquired.
    Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

    Exception Details: System.Security.Policy.PolicyException: Execution permission cannot be acquired.

    Source Error:

    An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

    Stack Trace:

    [PolicyException: Execution permission cannot be acquired.]
    System.Security.SecurityManager.ResolvePolicy(Evidence evidence, PermissionSet reqdPset, PermissionSet optPset, PermissionSet denyPset, PermissionSet& denied, Boolean checkExecutionPermission) +10236136
    System.Security.SecurityManager.ResolvePolicy(Evidence evidence, PermissionSet reqdPset, PermissionSet optPset, PermissionSet denyPset, PermissionSet& denied, Int32& securitySpecialFlags, Boolean checkExecutionPermission) +97

    [FileLoadException: Could not load file or assembly 'm2wivo6v, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. Failed to grant permission to execute. (Exception from HRESULT: 0x80131418)]
    System.Reflection.Assembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection) +0
    System.Reflection.Assembly.InternalLoad(AssemblyName assemblyRef, Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection) +416
    System.Reflection.Assembly.Load(AssemblyName assemblyRef, Evidence assemblySecurity) +33
    System.CodeDom.Compiler.CompilerResults.get_CompiledAssembly() +105…

    I’m running this code in SharePoint 2007 on Windows Server 2008.

  11. vikram - May 26, 2009

    It’s working fine but application memory increases when web service call are made 2500 times.

    Can we delete the temporary files created while compiling assembly ?

  12. marmri - May 31, 2009

    Hi,
    Thank you for this great example.
    I have the same problem as Sergio – May 14, 2009
    Did you wirte him any suggestion? Please forward it or add it in this article for the whole aucience!
    I have another question: how to do, if you have following situation:

    MyWebReference.GoodbyeWorldWSService myProxy = new MyWebReference.GoodbyeWorldWSService();
    MyWebReference.sayGoodbye request = new MyWebReference.sayGoodbye();
    request.message = “ciao”;
    myProxy.sayGoodbye(request);

    I mean, you have like an object as parameter you first initialize then invoke the service method!

    Please help, is urgent. Thanx a lot in advance

  13. Jeff - June 13, 2009

    Hi As I walk on the code.. i see that the reason why its throwing an exception on this line (T)type.InvokeMember(methodName, BindingFlags.InvokeMethod, null, obj, args); it is maybe because you are calling a method with complex (custom) type and not a generic type. try to have a breakpoint on that line and see the details of the “type” variable.

  14. shail - June 27, 2009

    I am using your example. But its giving me an error on InvokeMember that “The request failed with HTTP status 401: Access Denied” Is there anything special, i will have to do here?

    Thanks,

    Shail …

  15. RadoColo - June 30, 2009

    Beautiful, works like a charm!

  16. usmanbinasif - July 6, 2009

    Dear it is awesome code example of this problem domain, and it is very helpful for me.

    Thanks for sharing such a wonderful peice of code.

    Regards,
    Usman Javed

  17. newbieDotNET - July 7, 2009

    Will it be possible to invoke or set the timeout property? Any help would be greatly appreciated.

    Thanks,
    Jon

  18. David Roys - July 8, 2009

    What an awesome example. Well explained and a great download! Thank you for your time and effort. Unfortunately it doesn’t quite work for me.

    I am also having the problem with authentication that shail posted. I know that when I use my web service by generating the proxy class, I need to use the line:

    ws.UseDefaultCredentials = true in order to be able to user the service.

    I am getting the following error:

    Unable To Load Service: The remote server returned an error: (401) Unauthorized.

    when I click the Load Service button and I can only assume it is because the XMLTextReader is not negotiating my credentials. If I use Internet explorer to hit the URL it will give me the WSDL but I believe this is because it handles the challenge response correctly. Do I need to use another method of getting my WSDL – i.e. not using XMLTextReader?

    Thanks again for such a great post! I learnt a lot.

  19. Mark - July 8, 2009

    Good work, excellent explanation.

    functions that expect strings do work, but functions that expect other types (int, byte[], …) do not work.

    Any idea how to solve this?

    Thanks

    Mark

  20. David Roys - July 10, 2009

    Hi there, OK, I thought I would let other readers know that I managed to sort out my problems with authentication.

    You can read the details on a blog post I made http://www.teachmenav.com/blogs/dave/archive/2009/07/11/using-reflection-to-call-nav-2009-web-services.aspx

    Thanks again for the great post.

  21. Crows Programming » I’m Back - July 15, 2009

    [...] Hey guys, sorry I’ve been away for a bit. I’ll try and respond to your questions, especially those over on the C# dynamic web service page. [...]

  22. MaTZ - July 22, 2009

    Hi,
    I have a problem with http authentication.
    I managed to download WSDL by modifying BuildAssemblyFromWSDL like this:

    System.Net.WebClient client = new System.Net.WebClient();

    if (login.Length > 0)
    {
    client.Credentials = new NetworkCredential(login, password);
    }

    System.IO.Stream stream = client.OpenRead(webServiceUri.ToString() + “?wsdl”);

    XmlTextReader xmlreader = new XmlTextReader(stream);

    ServiceDescriptionImporter descriptionImporter = BuildServiceDescriptionImporter(xmlreader);

    return CompileAssembly(descriptionImporter);

    Now I’m getting exception (error 401) later when I try to invoke web method. Any ideas?

    Thanks for the post.

  23. Andrew Brown - August 4, 2009

    Very useful post. I have been using this technique for over a year.

    I am having a problem where the web service request takes longer than 110 seconds to return a response. This causes a timeout error. I have been troubleshooting the timeout issue by changing all configurable timeout settings from the application setting (web.config) and IIS.

    [Error Details]
    System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. —> System.Net.WebException: The operation has timed out.

    I setup a simple test where the web server thread sleeps for 2 mins and 30 seconds.

    Please post if anyone has solved this.

  24. Donald Drake - August 5, 2009

    ““Method ‘Service1.Sum’ not found” ”

    I was able to fix this error by using the following instead.

    MethodInfo method = type.GetMethod(methodName);
    return (T) method.Invoke(instance, args);

    I believe the issue is due to the fact that it is using BindingFlags.InvokeMethod.. I was not able to use any other bindingflag with the type.InvokeMember method.

    Hope this helps.

    Thanks,
    Don

  25. Andrew Brown - August 5, 2009

    I found a solution to the Timeout issue. I had to set the Timeout property of the proxy instance.

    [CODE]
    PropertyInfo propInfo = obj.GetType().GetProperty(“Timeout”);
    propInfo.SetValue(obj, 300000 /* set this to whatever timeout period you want */, null);

    Then invoke the method.

  26. Colin - August 14, 2009

    I am have problem casting the return value of the web service if the web service return a custom type object.

  27. Rich Larson - September 22, 2009

    This solution works for standard web-services that expose their WSDL with the XSD:Schema types embedded directly (like that from ASMX-based web services). However because of a bug in the Microsoft WSDL parser it blows up when pointed at WSDL that imports its XSD:Schema types (like that from WCF-based web services).

    I have looked at all the various means to solve this and came up with only one solid solution: Flatten it. Here are the steps for a solution:

    1. Download the WSDL from the web service.

    2. Interrogate it to see if it includes “Import” directives in the xsd:Schema elements.

    3. If it does NOT include imports, pass it through untouched and continue as normal – everything will work as planned.

    4. If it DOES include imports directives, go download them and inject them into the base WSDL so it looks just like it would as if they were there in the first place.

    5. After merging, pass that version of the WSDL document on to the rest of the process and it should work like a charm.

    Note: When injecting, make sure to clean up your namespaces in the wsdl:definitions element so that all represented namespaces are covered. WCF by default generates an XSD: namespace in the WSDL doc and an XS: namespace in the imported Schema type defintions and these will need to be merged to make everything work in the final document.

    I have done this and it works. If I get the time, I will see if I can post the full code somewhere.

    Rich Larson

  28. newbieDotNet - October 5, 2009

    I’ve added a username and password field in my webservice is their anyway to pass those values using this solution?

    Thanks In Advanced.

  29. Pavel - October 9, 2009

    Really cool thing!

  30. Yogaraj C - October 21, 2009

    Very good example :). I have one small issue in this example. I want to add custom header (security purpose) for each and every request. Meaning, all the request should contain element in it. How can i achieve this? If anybody knows please reply. Thanks in advance.
    Yogaraj.C

  31. Drewsifer - November 2, 2009

    Getting a weird error (after changing line 149 to show the oops error: “throw new Exception(“Compilation Error Creating Assembly” + oops.ToString());”) :


    System.Exception: :System.Exception: Compilation Error Creating Assemblyc:WindowsTempa_ztzipv.0.cs(13,14) : error CS0234: The type or namespace name Data does not exist in the namespace System (are you missing an assembly reference?) at WSInterface.WebServiceInvoker.CompileAssembly(ServiceDescriptionImporter descriptionImporter) in C:inetpubwwwrootWSInterfaceWebServiceInvoker.cs:line 146 at WSInterface.WebServiceInvoker.BuildAssemblyFromWSDL(Uri webServiceUri) in C:inetpubwwwrootWSInterfaceWebServiceInvoker.cs:line 177 at WSInterface.WebServiceInvoker..ctor(Uri webServiceUri) in C:inetpubwwwrootWSInterfaceWebServiceInvoker.cs:line 37 at

    System.Data is added as a reference and (in a using line, as always) any ideas?

  32. Drewsifer - November 2, 2009

    changed line to this: string[] references = new string[3] { “System.Web.Services.dll”, “System.Xml.dll” , “System.Data.dll”};

  33. Vivek - November 23, 2009

    I am facing problem casting the return value of the web service if the web service return a custom type object

  34. wyrm91 - November 26, 2009

    Hi!

    Im getting this error when i use this wonderfull example

    HRESULT: 0×80131418 (permissions error)

    I thougth that this only happen when you deploy the application, not in developers machine…

    I used caspol, but nothing happened.

    Any suggestion?

    Thanks

  35. Nancy - December 3, 2009

    Its a nice example but i have a problem
    i want to invoke web service dynamically from remote system.
    The above code was helpful for invoking web service from local host.
    What more code should i need gto write for above purpose.
    Reply asap.

  36. Nancy - December 3, 2009

    Thanks in advance..

  37. guy - December 7, 2009

    Very helpful post. thanks.

  38. Shadi Abu Hilal - December 18, 2009

    Thanks,
    You are very smart ;)

  39. Mike - January 7, 2010

    Very helpful post.

    I need to programmatically access the response XML message received from a request made from the dynamically generated proxy. One way to do this would be to add a behavior to the client endpoint that would intercept the message.

    Is there a way to add a behavior to the proxy?

    Thanks in advance.

  40. wan - February 4, 2010

    Hi,

    This is a great post. I tried for few web service and it works. However, yesterday i face a problem “Compilation error creating assembly” for a web service which is locally deployed(local pc).

    i tried on other web service (also local) with the same parameter, and it works. Is there any attribute/configuration that a web service for this “Web service Invoker”.

    The web service which gives error, works if i use it by adding web reference..

    Thanks.

  41. Hi, - February 4, 2010

    This page is great!!!

    I’m using your code, but i have a problem with the array reference. The web service uses a interop.XXXsap.dll and i don’t know how to do that reference, becouse i added it to an array reference “interop.XXXsap.dll” but it didn’t worked, I need to add this dll to my project Bin’s folder ?

  42. Wan - February 9, 2010

    Hi,

    I found my problem already. This web service invoker will give an error if the web service parameter or is returning dataset or arraylist. The error happens when it tries to cast to object.
    So i tried returning xmldocument and it works. However i face a new problem. My webservice is actually copying a file(csv||xls) to a certain destination and it returns the content of it through xml document. The params are string and bytes[]. The invoker gives exception when the size of the file is quite big (test file with 500Kb), making the bytes[] size bigger. Here, it will gives exception; “Exception has been thrown by the target of an invocation. —> System.InvalidOperationException: There is an error in XML document (1, 483495). —> System.Xml.XmlException: ‘’, hexadecimal value 0x1A, is an invalid character. Line 1, position 483495.
    at System.Xml.XmlTextReaderImpl.Throw(Exception e)

    I’m confuse here. If it is caused by Xml deserialization, why then it works fine with smaller file size.

  43. Fawad - February 23, 2010

    “““Method ‘Service1.Sum’ not found” ”

    I was able to fix this error by using the following instead.

    MethodInfo method = type.GetMethod(methodName);
    return (T) method.Invoke(instance, args);

    I believe the issue is due to the fact that it is using BindingFlags.InvokeMethod.. I was not able to use any other bindingflag with the type.InvokeMember method.

    Hope this helps.

    Thanks,
    Don”

    Thanks Don, it helped.

    What I need to know from Crow, we can have multiple methods to get data back in format of methods other than String, we should override it.

    Hehe don’t worry I just solved my problem. :D

  44. jordan - February 26, 2010

    any other solution to WSDL’s that contains imports besides flattening it?

    TIA

  45. Phani Kumar PV - March 25, 2010

    Hi,
    i am facing problem while trying to invoke the webservice from a sample website using the same code given . i created a web page and referred to the web Seriviceinvoker class file.
    When i use the folllowing url using the windows app given by u it is working fine.
    But when i try to do the same using my webapp it is throwing an error that the “The remote host cannot be found”
    in the follwong line of code at ServiceDescription.CanRead(xmlreader).

    private ServiceDescriptionImporter BuildServiceDescriptionImporter( XmlTextReader xmlreader )
    {

    if (!ServiceDescription.CanRead(xmlreader))

    Not able to understand why i am not able to access the same from web.

    Following is the WSDL link that i am trying to access..

    http://www.w3schools.com/webservices/tempconvert.asmx?WSDL

    Any pointers will be really helpful

    Regards,
    Phani

  46. Juanmmett - March 29, 2010

    Hello, very nice code!
    Someone knows how can I assign credentials to web service?
    Thank you very much.

  47. Venkat - April 23, 2010

    This works like a charm, but wondering how to add credentials for this

  48. LP - April 25, 2010

    I am also wondering how to add credentials to this?

  49. Venkat - April 26, 2010

    Got the code resolved :-

    public T InvokeMethod(string serviceName, string methodName, params object[] args)
    {
    // create an instance of the specified service
    // and invoke the method
    object obj = this.webServiceAssembly.CreateInstance(serviceName);

    Type type = obj.GetType();
    PropertyInfo propInfo = obj.GetType().GetProperty(“Credentials”);
    propInfo.SetValue(obj, new NetworkCredential(userName,password,domain), null);

    return (T)type.InvokeMember(methodName, BindingFlags.InvokeMethod, null, obj, args);
    }

  50. How to add a reference of dynamically compiled assembly ? « My experiences with .NET - April 28, 2010

    [...] Code to generate dynamic assembly for a web service proxy can be found at Dynamic Web Service Proxy Generation [...]

  51. Vaibhav - May 24, 2010

    Nice read. I am trying something else hope you know the solution already, I am trying to build XML requests rather then the compiled assembly way. Can you please tell me how to read the metadata using ServiceDescription class to list all methods and its input and output parameters and also the data types of the same.

    Currenty my code works only for .NET generated WSDL.

    Regards,
    Vaibhav

  52. virus - June 16, 2010

    I get the following exception infrequently when I try to invoke a method on a webservice. Out of 100 requests, 2 requests fails with the exception. Any idea what would be causing the issue?

    System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. —> System.Net.WebException: The underlying connection was closed: An unexpected error occurred on a receive. —> System.IO.IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host. —> System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host
    at System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)
    at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
    — End of inner exception stack trace —
    at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
    at System.Net.PooledStream.Read(Byte[] buffer, Int32 offset, Int32 size)
    at System.Net.Connection.SyncRead(HttpWebRequest request, Boolean userRetrievedStream, Boolean probeRead)
    — End of inner exception stack trace —
    at System.Web.Services.Protocols.WebClientProtocol.GetWebResponse(WebRequest request)
    at System.Web.Services.Protocols.HttpWebClientProtocol.GetWebResponse(WebRequest request)
    at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String methodName, Object[] parameters)
    at GemFireService.GetItem(String superset, String date, String urn)
    — End of inner exception stack trace —
    at System.RuntimeMethodHandle._InvokeMethodFast(Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner)
    at System.RuntimeMethodHandle.InvokeMethodFast(Object target, Object[] arguments, Signature sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner)
    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.RuntimeType.InvokeMember(String name, BindingFlags bindingFlags, Binder binder, Object target, Object[] providedArgs, ParameterModifier[] modifiers, CultureInfo culture, String[] namedParams)
    at System.Type.InvokeMember(String name, BindingFlags invokeAttr, Binder binder, Object target, Object[] args)
    at DashBoard_V001.WebServiceInvoker.InvokeMethod[T](String serviceName, String methodName, Object[] args) in C:\My_Projects\Citi_Projects\CITIDashboard\DashBoard_V001\DynamicWSDL\WebServiceHelper.cs:line 105
    2010-06-16 12:55:50,146 [11] DEBUG InvokeMethod – Message Exception has been thrown by the target of an invocation.
    2010-06-16 12:55:50,146 [11] DEBUG InvokeMethod – Source mscorlib
    2010-06-16 12:55:50,146 [11] DEBUG InvokeMethod – TargetSite System.Object _InvokeMethodFast(System.Object, System.Object[], System.SignatureStruct ByRef, System.Reflection.MethodAttributes, System.RuntimeTypeHandle)
    2010-06-16 12:55:50,146 [11] DEBUG InvokeMethod – Name _InvokeMethodFast
    2010-06-16 12:55:50,146 [11] DEBUG InvokeMethod – Stackstace at System.RuntimeMethodHandle._InvokeMethodFast(Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner)
    at System.RuntimeMethodHandle.InvokeMethodFast(Object target, Object[] arguments, Signature sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner)
    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.RuntimeType.InvokeMember(String name, BindingFlags bindingFlags, Binder binder, Object target, Object[] providedArgs, ParameterModifier[] modifiers, CultureInfo culture, String[] namedParams)
    at System.Type.InvokeMember(String name, BindingFlags invokeAttr, Binder binder, Object target, Object[] args)
    at DashBoard_V001.WebServiceInvoker.InvokeMethod[T](String serviceName, String methodName, Object[] args) in

  53. virus - June 17, 2010

    Another observation. I am calling the web method at a frequency of 15 seconds, the business requires it. At times, the request gets blocked at InvokeMethod. This is irrespective of the timeout..

  54. Av - June 29, 2010

    Thanks for the detailed code listing which compiles first time round :)

    I wanted to ask you however how you were getting your web services published at http://localhost/services/test.php so that the program can pick up the different web services available from that URL.

  55. 解惑 » 日志 » 用C#动态调用WebService - June 30, 2010

    [...] 其实利用的都是前人的成果:C# – Dynamically Invoke Web Service At Runtime [...]

  56. Saurabh Surana - July 5, 2010

    Hi,
    I want to create a .NET application which very much looks like the one that you have here. The only difference is, after getting the parameter info it also shows the SOAP message that will be sent for invoking each and every method exposed by the web services, to the users. I want to create a SOAP Ui kind of functionality using .NET.
    After looking at sample you attached here, I can see that, it uses ServiceDescriptionImportar on the WSDL and generates the stub class, but again it invokes the web serivce dynamically, I couldnt find a way of generating the SOAP message instead of calling the webservice.

    I think what I am looking for is very simple (one step less than sending the message), which is available for sure I am just not able to find it.

    Can anybody show me the way?

  57. sri - August 5, 2010

    Hi i am trying use this example with Wcf Webservice.
    I am getting an error stating unable to load Service :unable to import binding BasicHttpBinding_IcontractDocumentService from NameSpace: “http://tempuri.org/”.Can you tell me how resolve this issue.

  58. fghxu - August 5, 2010

    Hi Virus,
    Have you solve the TargetInvocationException issue?

    I am facing the same exception like yours. it does not faile on every call.

    System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. —> System.ServiceModel.CommunicationException: An error occurred while receiving the HTTP response to http://172.18.16.56:4640/. This could be due to the service endpoint binding not using the HTTP protocol. This could also be due to an HTTP request context being aborted by the server (possibly due to the service shutting down). See server logs for more details. —> System.Net.WebException: The underlying connection was closed: An unexpected error occurred on a receive. —> System.IO.IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host. —> System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host

  59. Zhuk - August 5, 2010

    Hi thanks for this post. How is this going to work with WSE3 Athentication?

  60. Ayırma Büyüsü - August 20, 2010

    I am getting an error stating unable to load Service :unable to import binding BasicHttpBinding_IcontractDocumentService from NameSpace: http://www.ayirmabuyusu.org :) Can you tell me how resolve this issue.

  61. Manthan - August 27, 2010

    I am not able to use the same code to connect to the http://www.w3schools.com/webservices/tempconvert.asmx?WSDL
    web service from within the Web Application i get the error ” The remote host cannot be found”. But the code works like a charm when I use it within a Windows application. I see the same issue was faced by some others in this forum and was wondering if anyone found a solution to the same.

  62. Selva - August 29, 2010

    This codes shows my web service’s methods name. But when I try to invoke this method it shows “Method not found” Error.

    URGENT. Please help me…

  63. Manthan - August 29, 2010

    I was able to resolve the issue with connecting to the remote webserivce. Look at my solution at the following site:

    http://stackoverflow.com/questions/3581451/dynamically-invoke-web-service-at-runtime/3597624#3597624

  64. John Saunders - August 29, 2010

    The code should change in at least two ways:

    1) “new XmlTextReader()” has been deprecated since .NET 2.0. You should use “XmlReader.Create()” instead.
    2) You should have “using” blocks around all objects implementing IDisposable. In particular, you should have

    using (XmlReader reader = XmlReader.Create(…))
    {
    }

  65. Manikandan - November 1, 2010

    Hi i tried your code., but for me it shows method not found error while invoke the web method. and also i want to know how to form input to the web mwthod.

    Plz reply me.

    Regards,
    Manikandan

  66. Web Service Communicator « Insights on Software Development and Architecture - February 8, 2011

    [...] a prior knowledge of its contract at build-time. As a result of my research I finally came accross http://www.crowsprogramming.com/archives/66, which follows the approach that I’ve explained in the introduction. I’ve built a [...]

  67. Tanvir - March 1, 2011

    Hi,
    I want to create a .NET application which very much looks like the one that you have here. The only difference is, after getting the parameter info it also shows the SOAP message that will be sent for invoking each and every method exposed by the web services, to the users. I want to create a SOAP Ui kind of functionality using .NET.
    It should have following features::
    1. It can hanle the cert issues.
    2. It can work for diffrent end points for diffrent environments.
    Please share the sample code with little bit details if anyone have done something like this..
    Thanks in advance.

  68. Shashank - June 1, 2011

    Dear SIr,
    I wanna invoke webservice methods & its request paramater and response paramater with dataype.
    and i also wanna that i will put webservices urll in textbox it will create class file fron that url in c#

    Thanksa
    in advance

  69. jay - July 17, 2011

    For some reason I keep hitting the warning NoCodeGenerated in ServiceDescriptionImportWarnings. I can’t find anything on what that might be and why. The servicedescription has consumed it the WSDL url fine and if i debug I can see the description information. Any ideas? My WCF service is basicHttp and it’s pretty simple. Thanks everyone.

  70. Christopher Zahrobsky - October 11, 2011

    I rewrote the generic InvokeMethod logic for my current implementation. The “InvokeMember(methodName” was failing.

    ///
    /// Invokes the specified method of the named service.
    ///
    /// The expected return type.
    /// The name of the service to use.
    /// The name of the method to call.
    /// The arguments to the method.
    /// The return value from the web service method.
    public T InvokeMethod(string serviceName, string methodName, params object[] args)
    {
    // create an instance of the specified service
    // and invoke the method
    T result = default(T);
    object obj = this.webServiceAssembly.CreateInstance(serviceName);
    Type type = obj.GetType();

    foreach (MethodInfo minfo in type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly))
    {
    if (minfo.Name.ToLower() == methodName.ToLower())
    {
    object[] availableArgs = new object[minfo.GetParameters().Length];
    for (int i = 0; i < availableArgs.Length; i++ )
    {
    availableArgs[i] = args[i];
    }
    result = (T)minfo.Invoke(obj, availableArgs);
    break;
    }
    }
    return result;
    }

  71. Jose Villagrana - October 20, 2011

    Hi, Very nice code!
    When the method that your invoke have any other parameter that is not string show an error. make this changes in the “public T InvokeMethod( string serviceName, string methodName, params object[] args )” and will works fine:

    MethodInfo method = type.GetMethod(methodName);
    foreach (MethodInfo minfo in type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly))
    {
    if (minfo.Name.ToLower() == methodName.ToLower())
    {
    ParameterInfo [] parametesrs = method.GetParameters();
    object[] availableArgs = new object[minfo.GetParameters().Length];
    for (int i = 0; i < availableArgs.Length; i++)
    {
    object value = Convert.ChangeType(args[i], Type.GetType(parametesrs[i].ParameterType.FullName));
    availableArgs[i] = value;
    }
    result = (T)minfo.Invoke(obj, availableArgs);
    break;
    }
    }
    return result;

  72. Jose Villagrana - October 20, 2011

    if your service has windows authentication add these lines in the method “private Assembly BuildAssemblyFromWSDL(Uri webServiceUri)”

    XmlTextReader xmlreader = new XmlTextReader(webServiceUri.ToString() + “?wsdl”);

    // Supply the credentials necessary to access the Web server.
    XmlUrlResolver resolver = new XmlUrlResolver();
    resolver.Credentials = new NetworkCredential(UserName, Password);
    xmlreader.XmlResolver = resolver;

  73. Joseph - October 27, 2011

    Please can you help me?

    I need to pass an int, string, ref struct to my webservice.

    How can I obtain the right value for ref struct?

    Cheers!

  74. Jean Moulis - October 31, 2011

    Good works and relevant contributions too!

    Nevertheless, in a production environment there are still several issues when you compile your assembly dynamically.

    See http://msdn.microsoft.com/en-us/library/ms366723.aspx for more information about disadvantages of dynamic compilation.

    Regards.

  75. Dennise - November 2, 2011

    Hi,

    Thanks for posting this code. I have one question, when I am create an instance of the webservice with extension .asmx, the code above is working fine.

    However, when I am trying to create an instance of the web service with extension .svc, I am alwasy getting the exception similar below:

    “unable to load Service :unable to import binding BasicHttpBinding_IcontractDocumentService from NameSpace: “http://tempuri.org/”.”

    Any ideas why?

    Thank you.

    Dennise

  76. lokesh - November 29, 2011

    when I am trying to create an instance of the web service with extension .svc, I am alwasy getting the exception similar below:

    “unable to load Service :unable to import binding BasicHttpBinding_IcontractDocumentService from NameSpace: “http://tempuri.org/”.”

    Any ideas why?

  77. alan gilchrist - February 1, 2012

    Sources…

    [...]check below, are some totally unrelated websites to ours, however, they are most trustworthy sources that we use[...]……

  78. neil - February 4, 2012

    Hi,
    I plan to have a web service running on IIS ( I am new to web services), does a web service stay running after a browser has requested information?

    I have written ISAPI , and as soon as it is called it stays in memory running. Saving a lot of time as it opens databases the first time it ran, and any future calls to it there is no need in opening theses databases.

    Neil

  79. muhammad hussain - February 13, 2012

    Error: Cannot find definition for CES.Services.FXGlobal:IRiaAsSender. Service Description with namespace CES.Services.FXGlobal is missing.
    Parameter name: name

    on line: ServiceDescriptionImportWarnings warning = descImporter.Import(codeNameSpace, compileUnit);

  80. Bean Bag Chair News | Bean Bag Chairs In Schools | Comfy ... - April 2, 2012

    Bean Bag Chairs for Autism Sensory Integration Therapy…

    [...]below you’ll find the link to some sites that we think you should visit[...]…

  81. Rik Boere - April 16, 2012

    I’ve got this working with credentials. the variable _credential is being set in the constructor and is of type NetworkCrednetial:

    NetworkCredential _credential;

    This is my BuildAssemblyFromWSDL:

    private Assembly BuildAssemblyFromWSDL(Uri webServiceUri)
    {
    if (String.IsNullOrEmpty(webServiceUri.ToString()))
    throw new Exception(“Web Service Not Found”);

    XmlTextReader xmlreader = new XmlTextReader(webServiceUri.ToString() + “?wsdl”);

    if (_credential != null)
    {
    // Supply the credentials necessary to access the Web server.
    XmlUrlResolver resolver = new XmlUrlResolver();
    resolver.Credentials = _credential;
    xmlreader.XmlResolver = resolver;
    }

    ServiceDescriptionImporter descriptionImporter = BuildServiceDescriptionImporter(xmlreader);

    return CompileAssembly(descriptionImporter);
    }

    I made this my InvokeMethod:

    public T InvokeMethod(string serviceName, string methodName, params object[] args)
    {
    // create an instance of the specified service
    // and invoke the method
    object obj = this.webServiceAssembly.CreateInstance(serviceName);

    Type type = obj.GetType();

    if (_credential != null)
    {
    PropertyInfo useDefaultCredentials = obj.GetType().GetProperty(“UseDefaultCredentials”);
    useDefaultCredentials.SetValue(obj, (object)false, new object[] { });

    PropertyInfo credentials = obj.GetType().GetProperty(“Credentials”);
    credentials.SetValue(obj, (object)_credential, new object[] { });
    }

    return (T)type.InvokeMember(methodName, BindingFlags.InvokeMethod, null, obj, args);
    }

  82. Matt M - May 1, 2012

    Thanks for the excellent article! For those getting the “unable to import binding” error, it’s because the wsdl has xsd imports. This article: http://www.west-wind.com/weblog/posts/2009/Feb/12/WSDL-Imports-without-WSDLexe demonstrates how to flatten the wsdl from the client side.

  83. Murillo - September 13, 2012

    Hi guys

    I was wondering if you could help me with an issue.

    I want to create a webservice that invokes another one.

    If I try to invoke a webservice, like a simple one we create through visual studio, it will load everything ok, the messages, the soap messages, etc.

    But if I pass a rest webservice for it, it doesn’t work:
    http://200.170.84.174:12001/Cejam/services/WPD?wsdl

    I hope you can help me

    tks

  84. Sudhakar - October 4, 2012

    Hi Guys,

    I need to get the Filed name and data type of that filed name from the dynamic web service calling.

    Please do the needfull..

  85. George - March 13, 2013

    Thanks a lot. you saved my time

  86. Jeff Dailey farmers insurance - April 20, 2013

    These are actually wonderful ideas in regarding blogging.
    You have touched some fastidious things here. Any way keep up wrinting.

  87. Marcelo - April 23, 2013

    So there are many virtual airlines that you can choose from and be their management.
    Now player can think that why they select this game.

    The atmosphere parameters calculated are: temperature, dew point, pressure density, wind
    (three-dimensional) and visibility. This kind of game is great because
    it can also provide scientific information, ‘Phun’ would help with physics study obviously while other simulation games that offer choices could contribute valuable data to Psychology.

    It features its own unique economy in which players can buy and sell things they make
    and so on, several real world companies are actually getting into the game to
    offer services, such as H&R Block.

  88. viagra - July 30, 2013

    You are so cool! I do not believe I have read through something
    like this before. So great to discover somebody with some
    genuine thoughts on this subject. Really.. thanks for starting this up.
    This website is one thing that is needed on
    the web, someone with a little originality!

  89. Armagan - August 5, 2013

    can you project shared please…

  90. y lib - December 17, 2013

    Tank you!! Its work!!

Leave a Reply

Connect with Facebook

*