Requirement:
I cannot use the MetadataExchangeClient as the WSDL will not be hosted.
Implementation:
var serviceDescription = ServiceDescription.Read(@"C:\Contacts.WSDL");
var metadataSection = new MetadataSection
{
Dialect = MetadataSection.ServiceDescriptionDialect,
Identifier = serviceDescription.TargetNamespace,
Metadata = serviceDescription
};
var metadataSections = new List<MetadataSection> {metadataSection};
var metadatSet = new MetadataSet(metadataSections);
var wsdlImporter = new WsdlImporter(metadatSet);
var services = wsdlImporter.ImportAllEndpoints();
Road Blocks:
object retVal = instance.GetType().GetMethod(operationName) .Invoke(instance, operationParameters); // Invoke
I tried by hard coding the operation name, manually parsed from the WSDL, but then it failed at the parameters. It's expecting a complex type containing the hierarchy as below :
ContactInput --> ListOfContacts --> Contact --> FirstName, LastName
Next Steps:
If someone could help me fix the roadblocks, then I can proceed with the above approach.
Else, I have to start researching on using the svcutil.exe at runtime
Thanks, Dev
There is a solution for doing this described in this article:
Generate proxy code for a web service dynamically
Although you can open that link and read it, I include the code here, just in case that link dies anytime:
This method returns the list of operations exposed by the web service. I have used ServiceDescription to achieve that as I was not able to reflect only the web method names from the generated assmebly. With the operation names available, all that remains is to find out the input and return parameters for each method.
public string[] GenerateProxyAssembly()
{
//create a WebRequest object and fetch the WSDL file for the web service
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(this.uri);
request.Credentials = CredentialCache.DefaultCredentials;
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
System.IO.Stream stream = response.GetResponseStream();
//read the downloaded WSDL file
ServiceDescription desc = ServiceDescription.Read(stream);
//find out the number of operations exposed by the web service
//store the name of the operations inside the string array
//iterating only through the first binding exposed as
//the rest of the bindings will have the same number
int i = 0;
Binding binding = desc.Bindings[0];
OperationBindingCollection opColl = binding.Operations;
foreach (OperationBinding operation in opColl)
{
listOfOperations[i++] = operation.Name;
}
//initializing a ServiceDescriptionImporter object
ServiceDescriptionImporter importer = new ServiceDescriptionImporter();
//set the protocol to SOAP 1.1
importer.ProtocolName = "Soap12";
//setting the Style to Client in order to generate client proxy code
importer.Style = ServiceDescriptionImportStyle.Client;
//adding the ServiceDescription to the Importer object
importer.AddServiceDescription(desc, null, null);
importer.CodeGenerationOptions = CodeGenerationOptions.GenerateNewAsync;
//Initialize the CODE DOM tree in which we will import the
//ServiceDescriptionImporter
CodeNamespace nm = new CodeNamespace();
CodeCompileUnit unit = new CodeCompileUnit();
unit.Namespaces.Add(nm);
//generating the client proxy code
ServiceDescriptionImportWarnings warnings = importer.Import(nm, unit);
if (warnings == 0)
{
//set the CodeDOMProvider to C# to generate the code in C#
System.IO.StringWriter sw = new System.IO.StringWriter();
CodeDomProvider provider = CodeDomProvider.CreateProvider("C#");
provider.GenerateCodeFromCompileUnit(unit, sw, new CodeGeneratorOptions());
//creating TempFileCollection
//the path of the temp folder is hardcoded
TempFileCollection coll = new TempFileCollection(@"C:\wmpub\tempFiles");
coll.KeepFiles = false;
//setting the CompilerParameters for the temporary assembly
string[] refAssembly = { "System.dll", "System.Data.dll",
"System.Web.Services.dll", "System.Xml.dll" };
CompilerParameters param = new CompilerParameters(refAssembly);
param.GenerateInMemory = true;
param.TreatWarningsAsErrors = false;
param.OutputAssembly = "WebServiceReflector.dll";
param.TempFiles = coll;
//compile the generated code into an assembly
//CompilerResults results = provider.CompileAssemblyFromDom(param, unitArr);
CompilerResults results
= provider.CompileAssemblyFromSource(param, sw.ToString());
this.assem = results.CompiledAssembly;
}
//return the list of operations exposed by the web service
return listOfOperations;
}
This method returns the input parameters in ParameterInfo[] list. To get the output parameter, just replace the call to GetParamters() on MethodInfo class with ReturnParameter property and put that inside a new method. Put these 3 methods inside a dll and add a reference to it from any client application. That's all. Just provide the URL and consume the web service, any web service. You don't have to go through the procedure of creating a proxy file every time you want to consume a new web service.
public ParameterInfo[] ReturnInputParameters(string methodName)
{
//create an instance of the web service type
//////////////to do/////////////////////////
//get the name of the web service dynamically from the wsdl
Object o = this.assem.CreateInstance("Service");
Type service = o.GetType();
ParameterInfo[] paramArr = null;
//get the list of all public methods available in the generated //assembly
MethodInfo[] infoArr = service.GetMethods();
foreach (MethodInfo info in infoArr)
{
//get the input parameter information for the
//required web method
if (methodName.Equals(info.Name))
{
paramArr = info.GetParameters();
}
}
return paramArr;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With