Consuming and Calling SOAP WebServices at Run Time - Dynamic Web Service Client from WSDL File

Requirements:

  • The client must provide the WSDL of the SOAP Web service at run time. i) select the WSDL file from the file sharing folder.
  • Use WSDL and call the method selected by the Client in the user interface, and process the response.

I can not use MetadataExchangeClient, because 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:

  • The above code could not retrieve the service endpoints at all. So, I had to manually create the service endpoint.
  • I could not list all the methods contained in the above WSDL, and the related I / O in the step (for use in the variables operationName and operationParameters below)
 object retVal = instance.GetType().GetMethod(operationName) .Invoke(instance, operationParameters); // Invoke 

I tried hard-coded the name of the operation, manually parsed from WSDL, but then it failed in the parameters. It expects a complex type containing a hierarchy, as shown below:

ContactInput → ListOfContacts → Contact → FirstName, LastName

Next steps:

If someone can help me fix the roadblocks, I can continue this approach.

Finally, I have to start researching the use of svcutil.exe at runtime

Thanks Dev

+5
source share
1 answer

There is a solution for this described in this article:

Dynamically generate proxy code for web service

Although you can open this link and read it, I am including the code here, just in case this link dies at any time:

This method returns a list of operations opened by the web service. I used ServiceDescription to achieve this, as I couldn’t only reflect the web method names from the assmebly created. Given the names of the operations, 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 the ParameterInfo [] list. To get the output parameter, simply replace the GetParamters () call on the MethodInfo class with the ReturnParameter property and put it in the new method. Put these 3 methods inside the dll and add a link to it from any client application. All this. Just provide the URL and use the web service, any web service. You do not need to go through the process of creating a proxy file every time you want to use 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; } 
+5
source

Source: https://habr.com/ru/post/1207724/


All Articles