CSharp Calling Different Web Services


Note: I have moved to blog at my own domain, so kindly visit this post over there for recent updates or comments. http://www.imranbalouch.com/blog/index.php/2010/05/csharp-calling-different-web-services/

If you are developing an application that has to call different webservices and at run time the application get to know that which method of which web service it has to call than you can use the following code:

using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Security.Permissions;
using System.Web.Services.Description;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
namespace CallbackWindowsService
{
public class DynamicWebService
{
[SecurityPermissionAttribute(SecurityAction.Demand, Unrestricted = true)]
internal static ReturnedObject CallWebService(string webServiceAsmxUrl, string userName, string password, string serviceName, string methodName, object[] args)
//internal static object CallWebService(string webServiceAsmxUrl, string serviceName, string methodName, object[] args)
{
System.Net.WebClient client = new System.Net.WebClient();
ReturnedObject retObj = new ReturnedObject();
try
{
if (userName.Length > 0)
{
client.Credentials = new NetworkCredential(userName, password);
}
System.IO.Stream stream = null;
// Connect To the web service
try
{
stream = client.OpenRead(webServiceAsmxUrl + “?wsdl”);
}
catch (Exception ex)
{
//”Unable to connect to the remote server”
retObj.ServiceIssues = Convert.ToInt64(ServiceIssues.ServiceNotAvailable);
retObj.ErrorMessage = ex.Message;
retObj.ReturnObject = null;
return retObj;
}
// 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.ProtocolName = “default”;
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)
{
String errMessage = String.Empty;
foreach (CompilerError oops in results.Errors)
{
errMessage += oops.ErrorText + “…”;
}
retObj.ServiceIssues = Convert.ToInt64(ServiceIssues.AssemblyCompilingError);
retObj.ErrorMessage = errMessage;
retObj.ReturnObject = null;
return retObj;
}
// Finally, Invoke the web service method
object wsvcClass = results.CompiledAssembly.CreateInstance(serviceName);
MethodInfo mi = wsvcClass.GetType().GetMethod(methodName);
object obj = mi.Invoke(wsvcClass, args);
retObj.ReturnObject = obj;
retObj.ServiceIssues = Convert.ToInt64(ServiceIssues.ProcessedSuccessfully);
}
else
{
retObj.ServiceIssues = Convert.ToInt64(ServiceIssues.NullObject);
retObj.ErrorMessage = “Response Object cannot be created.”;
retObj.ReturnObject = null;
}
return retObj;
}
else
{
retObj.ServiceIssues = Convert.ToInt64(ServiceIssues.ServiceImportWarning);
String errormsg = String.Empty;
switch (warning)
{
case ServiceDescriptionImportWarnings.NoCodeGenerated:
errormsg = “Service Warning: No Code Generated”;
break;
case ServiceDescriptionImportWarnings.NoMethodsGenerated:
errormsg = “Service Warning: No Methods Generated”;
break;
case ServiceDescriptionImportWarnings.RequiredExtensionsIgnored:
errormsg = “Service Warning: Required Extensions Ignored.”;
break;
case ServiceDescriptionImportWarnings.WsiConformance:
errormsg = “Service Warning: Service does not conform to the WS-I Basic Profile.”;
break;
default:
errormsg = “Service Warning: Unknown warning occured with code, ” + warning.ToString() + “.”;
break;
}
retObj.ErrorMessage = errormsg;
retObj.ReturnObject = null;
return retObj;
}
}
catch (Exception ex)
{
retObj.ServiceIssues = Convert.ToInt64(ServiceIssues.UnknownException);
retObj.ErrorMessage = ex.Message;
retObj.ReturnObject = null;
return retObj;
}
}
public DynamicWebService()
{
ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(SSLResult);
}
public Boolean SSLResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
return true;
}
}
public class ReturnedObject
{
public ReturnedObject()
{
}
public object ReturnObject
{
get;
set;
}
public Int64 ServiceIssues
{
get;
set;
}
public String ErrorMessage
{
get;
set;
}
}
public enum ServiceIssues
{
ServiceNotAvailable = 1,
ProcessedSuccessfully = 2,
ClientReturnedNULLObject = 3,
ServiceImportWarning = 4,
AssemblyCompilingError = 5,
UnknownException = 6,
NullObject = 7
}
}

If the webservice you are calling is accepting some object as input parameter you will get an exception that YourObjectType can not be converted to YourObjectType’.

To resolve this issue, replace the following line:

object obj = mi.Invoke(wsvcClass, args);

with

ParameterInfo[] pm = mi.GetParameters();
object ob;
object[] y = new object[1];
YourObjectType objResponse = null;
if (args.Length > 0)
{
objResponse = (YourObjectType)args[0];
}
if (objResponse != null)
{
foreach (ParameterInfo paraminfo in pm)
{
ob = results.CompiledAssembly.CreateInstance(paraminfo.ParameterType.Name);
//Some Junk Logic to get the set the values to the properties of the custom Object
foreach (PropertyInfo propera in ob.GetType().GetProperties())
{
if (propera.Name == “Property1″)
{
propera.SetValue(ob, objResponse.Property1, null);
}
else if (propera.Name == ” Property2″)
{
propera.SetValue(ob, objResponse.Property2, null);
}
}
y[0] = ob;
}
}
object obj = mi.Invoke(wsvcClass, y);

In this above code you will be getting parameters of method and loop on them, create object of the type which WebService is expecting, assign values to the object and call Invoke method.

Happy Development

=================================================================================
Updated On: 20th July 2011
An Update in this context, recently i came across a web service that was written in php and was using Soap as protocol, so the above code was generating NoCodeGeneratedWarning, so i gave it a quick fix.
Before line
if (warning == 0) // If zero then we are good to go
I placed this line of code,
if (warning == ServiceDescriptionImportWarnings.NoCodeGenerated)
{
importer.ProtocolName = “Soap”;
warning = importer.Import(nmspace, unit1);
}
It was the quickest fix i can do for it, however we can put this protocol name in database for each service and assign it accordingly.
Cheers
===============================================================================
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: