C#:C#Call WebService

Reference web address: https://www.cnblogs.com/dotnet261010/p/12461930.html

1. Preface

In your daily work, when it comes to interface docking with third parties, some use the WebService approach. This article focuses on how to invoke WebService in the.NET Framework. First, we create a WebService with two methods: one without parameters and one with parameters:

Once you've created a WebService, deploy it to IIS and make sure it's accessible

2. Static References

This method calls the WebService by adding a static reference. First, create a Winform program with a button on the interface that calls WebService:

Then add a static reference. Select the reference on the project that you want to call WebService, and right-click Add Service Reference, as shown in the following figure:

  Then enter the WebService address deployed on IIS:

The final click on the OK button completes the static reference to the WebService, and the project structure after the addition is complete is as follows:

Once you've added the references, you can write code:

/// <summary>
///Static call to WebService
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btn_Static_Click(object sender, EventArgs e)
{
    // instantiate
    CallWebService.TestWebSoapClient client = new CallWebService.TestWebSoapClient();
    // Call HelloWorld method without parameters
    string value1= client.HelloWorld();
    // Invoke a method with parameters
    string value2 = client.Test("Parametric method");
    // output
    MessageBox.Show($"Parameterless method return value:{value1},Return value of parametric method:{value2}");
}

Run program tests:

This allows you to call WebService.  

3. Dynamic Calls

We've said above how to invoke a WebService using a static reference, but this has one drawback: if the published WebService address changes, you need to re-add the reference to the WebService. If the existing WebService changes, the existing service references will also be updated, which requires code to be put on the spot. So is there any way to solve this problem? That's how you use dynamic calls to WebServices.

We add configurations to the configuration file, including the address of the WebService, the class name provided by the WebService, and the method name to be invoked:

<appSettings>
    <!--WebService address-->
    <add key="WebServiceAddress" value="http://localhost:9008/TestWeb.asmx"/>
    <!--WebService Provided Class Name-->
    <add key="ClassName" value="TestWeb"/>
    <!--WebService Method Name-->
    <add key="MethodName" value="Test"/>
    <!--Deposit dll Address of the file-->
    <add key="FilePath" value="E:\Test"/>
</appSettings>

Add a button to the interface, click it to invoke WebService dynamically, create a new help class:

using System;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.IO;
using System.Net;
using System.Text;
using System.Web;
using System.Web.Caching;
using System.Web.Services.Description;
using System.Xml.Serialization;

namespace WebServiceDemo
{
    public class WebServiceHelper
    {
        /// <summary>
        ///Generate dll file to save locally
        /// </summary>
        /// <param name="url">WebService address</param>
        /// <param name="className">class name</param>
        /// <param name="methodName">method name</param>
        /// <param name="filePath">Path to save dll file </param>
        public static void CreateWebServiceDLL(string url,string className, string methodName,string filePath )
        {
            // 1. Use WebClient to download WSDL information.
            WebClient web = new WebClient();
            Stream stream = web.OpenRead(url + "?WSDL");
            // 2. Create and format WSDL documents.
            ServiceDescription description = ServiceDescription.Read(stream);
            //Create a file folder if it doesn't exist
            if (Directory.Exists(filePath) == false)
            {
                Directory.CreateDirectory(filePath);
            }

            if (File.Exists(filePath + className + "_" + methodName + ".dll"))
            {
                //Determine if the cache is expired
                var cachevalue = HttpRuntime.Cache.Get(className + "_" + methodName);
                if (cachevalue == null)
                {
                    //Cache expiration deletion dll
                    File.Delete(filePath + className + "_" + methodName + ".dll");
                }
                else
                {
                    // Return directly if the cache has not expired
                    return;
                }
            }

            // 3. Create a client proxy proxy class.
            ServiceDescriptionImporter importer = new ServiceDescriptionImporter();
            // Specify the access protocol.
            importer.ProtocolName = "Soap";
            // Generate client proxy.
            importer.Style = ServiceDescriptionImportStyle.Client; 
            importer.CodeGenerationOptions = CodeGenerationOptions.GenerateProperties | CodeGenerationOptions.GenerateNewAsync;
            // Add a WSDL document.
            importer.AddServiceDescription(description, null, null);
            // 4. Compile client proxy classes using CodeDom.
            // Add a namespace for the proxy class, defaulting to the global space.
            CodeNamespace nmspace = new CodeNamespace();       
            CodeCompileUnit unit = new CodeCompileUnit();
            unit.Namespaces.Add(nmspace);
            ServiceDescriptionImportWarnings warning = importer.Import(nmspace, unit);
            CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");
            CompilerParameters parameter = new CompilerParameters();
            parameter.GenerateExecutable = false;
            // You can specify any file name you want.
            parameter.OutputAssembly = filePath + className + "_" + methodName + ".dll";  
            parameter.ReferencedAssemblies.Add("System.dll");
            parameter.ReferencedAssemblies.Add("System.XML.dll");
            parameter.ReferencedAssemblies.Add("System.Web.Services.dll");
            parameter.ReferencedAssemblies.Add("System.Data.dll");
            // Generate a dll file and write WebService information into the dll
            CompilerResults result = provider.CompileAssemblyFromDom(parameter, unit);
            if (result.Errors.HasErrors)
            {
                // Display compilation error information
                System.Text.StringBuilder sb = new StringBuilder();
                foreach (CompilerError ce in result.Errors)
                {
                    sb.Append(ce.ToString());
                    sb.Append(System.Environment.NewLine);
                }
                throw new Exception(sb.ToString());
            }
            //Record Cache
            var objCache = HttpRuntime.Cache;
            // Cache information written to dll file
            objCache.Insert(className + "_" + methodName, "1", null, DateTime.Now.AddMinutes(5), TimeSpan.Zero, CacheItemPriority.High, null);
        }
    }
}

Dynamic invocation of WebService code:

/// <summary>
///Dynamic call to WebService
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btn_Dynamic_Click(object sender, EventArgs e)
{
    // Read the configuration file for configuration information
    string url = ConfigurationManager.AppSettings["WebServiceAddress"];
    string className = ConfigurationManager.AppSettings["ClassName"];
    string methodName = ConfigurationManager.AppSettings["MethodName"];
    string filePath = ConfigurationManager.AppSettings["FilePath"];
    // Call WebServiceHelper
    WebServiceHelper.CreateWebServiceDLL(url, className, methodName, filePath);
    // Read dll content
    byte[] filedata = File.ReadAllBytes(filePath + className + "_" + methodName + ".dll");
    // Load assembly information
    Assembly asm = Assembly.Load(filedata);
    Type t = asm.GetType(className);
    // Create an instance
    object o = Activator.CreateInstance(t);
    MethodInfo method = t.GetMethod(methodName);
    // parameter
    object[] args = {"Dynamic Call WebService" };
    // Call access to get method return value
    string value = method.Invoke(o, args).ToString();
    //Output Return Value
    MessageBox.Show($"Return value:{value}");
}

Program run results:

If the class name is not provided, you can automatically get the class name based on the url:

/// <summary>
///Get className from the url address of the WebService
/// </summary>
/// <param name="wsUrl">url address of WebService</param>
/// <returns></returns>
private  string GetWsClassName(string wsUrl)
{
    string[] parts = wsUrl.Split('/');
    string[] pps = parts[parts.Length - 1].Split('.');
    return pps[0];
}

Posted on Fri, 26 Nov 2021 22:55:42 -0500 by DoctorWho