Preface
From the developer's point of view, WebService technology is really no longer "trendy". Even a lot of people would say that we no longer use it. Of course, in order for the software to be more concise, more layered, and easier to implement caching mechanisms, I would highly recommend SOAP to a RESTful architectural style. But so far, WebService is widely used in some public institution.
Here is the main discussion about the invocation of the WebService problem. The invocation of WebService is divided into static call and dynamic call two kinds.
Static Call
Static calls are made by "Add Service Reference ..." To create a client proxy class. This approach allows the vs.net environment to generate a service proxy for us and then invoke the corresponding Web service. This makes the work simple, but binds the URL, method name, and parameters of the Web service together, which is the limit that vs.net automatically generates for us with the Web service proxy. If the URL of the publishing Web service changes, then we need to re-let Vs.net build the agent and recompile. It is a common scenario that a bank Web service, because of the deployment of the URL changes, and has to recompile the build agent, this will bring a lot of unnecessary effort. This can be avoided if we use dynamic invocation. The static call is not the focus of this article, so it is not described in detail.
Dynamic Invocation
In some cases we need to invoke a service dynamically while the program is running. There is something we need in the System.Web.Services.Description namespace of the. NET Framework. Dynamic calls have 3 ways of dynamically calling WebService, generating client Agent assembly files, and generating client proxy class source code.
The specific steps for dynamic invocation are:
1) Download the WSDL data from the destination URL;
2) Create and format a WSDL document file using ServiceDescription;
3) Create a client proxy class using ServiceDescriptionImporter;
4) Dynamically create client proxy class assemblies using CodeDom;
5) Call the relevant WebService method with reflection.
The first method completes the dynamic call process by creating a dynamic assembly in memory, and the second method saves the client proxy class generation assembly file to the hard disk, which can then be loaded and reflected by Assembly.LoadFrom (). For systems that require multiple calls, it is much more efficient than generating dynamic assemblies each time, and the third Way is to save the source file to the hard disk and then make the reflection call.
This will only be the second way, which is the most commonly used in practical applications. This method only downloads the WSDL information once and creates the assembly of the proxy class. Each time the program starts, it will reflect the previously created assembly. In the case of a Web service URL change, you only need to modify the WebServiceURL and Proxyclassname configuration items in App. config and remove the assemblies generated under the program root. The next time the program starts, the WSDL information is re-downloaded and the assembly of the proxy class is created.
App. Config file.
1 <?xml version= "1.0" encoding= "Utf-8"?> 2 <configuration> 3 <appSettings> 4 <!-- WebService Address--5 <add key= "WebServiceURL" value= "http://localhost:25060/testService/"/> 6 <!- -webservice Output DLL file name--7 <add key= "Outputdllfilename" value= "TestWebService.dll"/> 8 <!-- WebService proxy class name---9 <add key= "Proxyclassname" value= "Testservice"/>10 </appsettings>11 </configuration>
Create a proxy class.
1 public class Wshelper 2 {3//<summary> 4///output DLL file name 5//</summar Y> 6 private static string m_outputdllfilename; 7 8//<summary> 9//WebService proxy class name///</summary> one private static String M_proxyclassname; //<summary>//WebService Agent class instance///</summary> + private Stati C Object M_objinvoke; ///<summary> 19//interface method dictionary///</summary> private static diction Ary<emethod, methodinfo> m_methoddic = new Dictionary<emethod, methodinfo> (); //<summary> 24///Create WebService, generate client Agent assembly files///</summary> 26// <param name= "Error" > Error message </param>//<returns> return: TRUE or false</returns> Publi C static bool Createwebservice (out string error) 29 {30 Try to {error = string. Empty; M_outputdllfilename = configurationmanager.appsettings["Outputdllfilename"]; M_proxyclassname = configurationmanager.appsettings["Proxyclassname"]; String webserviceurl = configurationmanager.appsettings["WebServiceURL"]; WebServiceURL + = "? WSDL "; 37 38//If the assembly already exists, use the file.exists directly (Path.Combine (Environment.currentdirectory, M_ou Tputdllfilename)) ()) (buildmethods); 43 } 44 45//Use WebClient to download WSDL information. WebClient Web = new WebClient (); Stream stream = web. OpenRead (WebServiceURL); 48 49//Create and format WSDL documents. (Stream! = null) 51 {52//formatted WSDL Servi Cedescription DESCRIption = Servicedescription.read (stream); 54 55//Create a client proxy class. ServiceDescriptionImporter importer = new ServiceDescriptionImporter 57 {58 ProtocolName = "Soap", "servicedescriptionimportstyle.client Style =", 60 CodeGenerationOptions = Codegenerationoptions.generateproperties | Codegenerationoptions.generatenewasync 62}; 63 64//Add WSDL document. Importer. Addservicedescription (description, NULL, NULL); 66 67//Use CODEDOM to compile the client proxy class. 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 76 {77 GenerateExecutable = False, 78//Specifies the output DLL file name. outputassembly = M_outputdllfilename 80}; Bayi parameter. Referencedassemblies.add ("System.dll"); Parameter. Referencedassemblies.add ("System.XML.dll"); Parameter. Referencedassemblies.add ("System.Web.Services.dll"); Parameter. Referencedassemblies.add ("System.Data.dll"); 86 87//Compile output assembly compilerresults result = provider. CompileAssemblyFromDom (parameter, unit); 89 90//Use Reflection to call WebService. if (!result. errors.haserrors) (Buildmethods) (94) return true; 98 error = "Reflection generates DLL text Exception "; }100 Stream. Close (); 101 stream. Dispose (); 102}103 else104 {error = "Open Webserviceu RL failed "; 106}107}108 catch (Exception ex) 109 {$ error = ex. message;111}112 return false;113}114 +//<summary>116//reflection Construction Methods117//</summary>118 private static void Buildmethods () 119 {Assembly ASM = Assembly.LoadFrom (m_outputdllfilename); 121//var types = asm. GetTypes (); 122 Type Asmtype = asm. GetType (m_proxyclassname); 123 M_objinvoke = Activator.CreateInstance (asmtype); 124//var methods = asmtype.getmethods (); 126 var methods = Enum.getnames (typeof (Emethod)). ToList (); 127 foreach (var item in methods): {129 var methodInfo = Asmtype.getmet Hod (item); if (methodInfo! = null) 131 {$ var method = (Emethod) En Um. Parse (typeof (Emethod), item), 133 M_methoddic.add (method, MethodInfo); 134}135 }136}137 138///<summary>139//Get request response from//</summary>141// <param name= "Method" > Methods </param>142//<param name= "para" > Parameter </param>143//<r Eturns> return: JSON string </returns>144 public static string Getresponsestring (Emethod method, params object[] para) 145 {146 String result = null;147 if (M_methoddic.containskey (method)) 148 {149 var temp = M_methoddic[method]. Invoke (m_Objinvoke, para); if (temp! = null) 151 {result = temp. ToString (); 153}154}155 return result;156}157}
Invokes an interface.
1 //SOAP Request Response Mode 2 TextBox3.Text = wshelper.getresponsestring (Emethod.add, Convert.ToInt32 (TextBox1.Text), Convert.ToInt32 (TextBox2.Text));
HTTP request
In addition to static calls and dynamic calls, we can also send HttpPost requests to call WebService's methods. A SOAP request is a dedicated version of HTTP POST, followed by a special XML message format. Using the HttpPost request, we can parse the returned results manually. The following implementation is actually exactly the same as calling Webapi.
1//<summary> 2//Request information Help 3//</summary> 4 public partial class Httphelper 5 { 6 private static Httphelper m_helper; 7//<summary> 8///single 9//</summary> public static Httphelper Helper {get {return m_helper?? (M_helper = new Httphelper ()); }//<summary> 16///Get the requested data///</summary>///&L T;param name= "strURL" > Request address </param>//<param name= "Requestmode" > Request mode </param> 20/ <param name= "Parameters" > Parameters </param>//<param name= "requestcoding" > Request encoding </param> 22 <param name= "responsecoding" > Response code </param>//<param name= "Timeout" > Request time-out (milliseconds) < ;/param>//<returns> return: Request Successful response information, failed to return null</returns> public string getresponsestring ( String strURL, Erequestmode Requestmode, dictionary<string, string> parameters, Encoding requestcoding, Encoding responsecoding, int timeout = +) (string url = Verifyurl (strURL); httpwebreque St WebRequest = (HttpWebRequest) webrequest.create (new Uri (URL)); HttpWebResponse WebResponse = null; Switch (requestmode), erequestmode.get:34 Webr Esponse = getrequest (webRequest, timeout); break; erequestmode.post:37 WebResponse = postrequest (webRequest, parameters, Timeou T, requestcoding); a break; (WebResponse! = null && Webresponse.statuscode = = Httpstatuscode.ok) 42 {newstream Using Stream = WebResponse.GetResponseStream ()) 44 {45 if (newstream! = null) 46 using (StreamReader reader = new StreamReader (newstream, responsecoding)) 47 { The string result = Reader. ReadToEnd (); The return result; A. {} *}, and return null; */<summary>//Get request Specify address return response data///</summary> 60 <param name= "WebRequest" > Request </param>//<param name= "Timeout" > Request time-Out (ms) </PARAM&G T +//<returns> return: Response information </returns> HttpWebResponse getrequest (HttpWebRequest webrequ EST, int timeout), {webrequest.accept = "text/html, appl Ication/xhtml+xml, Application/json, Text/javascript, */*; q=0.01 "; WEBREQUEST.HEADERS.ADD ("Accept-language", "zh-cn,en-us,en;q=0.5"); WebreqUest. Headers.add ("Cache-control", "No-cache"); Webrequest.useragent = "Defaultuseragent"; Webrequest.timeout = Timeout; Webrequest.method = "GET"; 73 74//Receive return information HttpWebResponse WebResponse = (httpwebresponse) webrequest.getresponse ( ); WebResponse return; 81} 82 (Exception ex) (n) }//<summary>//POST request specify address return response data///</summary> 88 <param name= "WebRequest" > Request </param>//<param name= "parameters" > Incoming Parameters </param> 90 <param name= "Timeout" > Request time-Out (ms) </param>//<param name= "requestcoding" > Request encoding < ;/param>//<returns> return: Response information </returns> HttpWebResponse postrequest (httpwebre Quest WebRequest, Dictionary<string, string> parameters, int timeout, Encoding requestcoding) 94 {try 96 {97//Stitching parameter 98 string poststr = String. Empty; if (Parameters! = null) {101 parameters. All (o =>102 {103 if (string. IsNullOrEmpty (POSTSTR)) 104 Poststr = string. Format ("{0}={1}", O.key, O.value); else106 poststr + = string. Format ("&{0}={1}", O.key, O.value); 107 108 Return true;109}); 110 }111 byte[] ByteArray = requestcoding.getbytes (POSTSTR); 113 webrequest.accept = "text/html, Application/xhtml+xml, Application/json, Text/javascript, */*; q=0.01 "WebRequest.Headers.Add (" Accept-language "," zh-cn,en-us,en;q=0.5 "); 115WEBREQUEST.HEADERS.ADD ("Cache-control", "No-cache"); webrequest.useragent = "defaultuseragent"; 117 Webrequest.timeout = timeout;118 Webrequest.contenttype = "application/x-www-form-urlencoded"; 119 Webrequest.contentlength = bytearray.length;120 Webrequest.method = "POST"; 121 122 Write parameters to stream 123 using (Stream newstream = Webrequest.getrequeststream ()) 124 {125 Newstream.write (ByteArray, 0, bytearray.length); 126 newstream.close (); 127 }128 129//Receive return information HttpWebResponse WebResponse = (httpwebresponse) webrequest.g Etresponse (); 131 return webresponse;132}133 catch (Exception ex) 134 { 135 return null;136}137}138 139//<summary>141//Authentication URL 142//</summary>143//<param name= "url" > Pending verification url</param>144//<returns></returns>145 private string Verifyurl (string url) 146 {147 if (string. IsNullOrEmpty (URL)) 148 throw new Exception ("URL address cannot be empty! "); 149 if (URL. StartsWith ("http//", stringcomparison.currentcultureignorecase)) 151 return url;152 153 return String. Format ("http://{0}", url); 154}155}
The httppost invokes the interface in response to the request.
1 //Http Post Request Response Mode 2 String url = m_webserviceurl + EMethod.Add.ToString (); @ "HTTP://LOCALHOST:25060/TESTSERVICE.ASMX/ADD"; 3 dictionary<string, string> parameters = new Dictionary <string, string> {{"Parameter1", TextBox1.Text}, {"Parameter2", TextBox2.Text}};4 string result = Httphelp Er. Helper.getresponsestring (URL, erequestmode.post, parameters, Encoding.default, Encoding.UTF8); 5 XElement root = Xelement.parse (result); 6 textbox3.text = root. Value;
about soap and rest
We all know that rest is more lightweight than soap's recommended standard and can be invoked with JavaScript, which is more convenient, efficient, and easy to use. But it is not that rest is a substitute for soap. They are just two different architectural styles that implement Web service (Web services). As far as security is concerned, soap is better.
C # WebService Dynamic invocation