Consolidating distributed applications is often a difficult and complex task, and even the most experienced developers may find it frustrating. This integration problem becomes particularly complex when the application is operating on a different OS and involves different program platforms. While Web service commitments can ease the difficulty of programmers accomplishing integration tasks, they can also cause unexpected problems for programmers. Here we will link a asp.net application with a PHP Web service to learn some ways to integrate distributed applications and the necessary responses, including what to run and what not to do.
This web service runs on an Apache server and is developed using PHP. It retrieves news summaries and their associated text from a variety of Microsoft newsgroups. Even the data provided by this service can be used directly from the internal. NET object access, but this service will still use and provide a connection to the non. NET platform for a good demo. The example we are going to discuss here is based on. Net Beta version 2.
Create a Web service proxy
Visual Studio.NET provides an excellent mechanism for automatically generating proxy pairs that can be used to access remote Web services. Therefore, you first attempt to use these functions to import the Web Service Description Language (Web services Description language,wsdl) files that are provided by the PHP service. You can also use the WSDL.exe command line utility for the. Net SDK. Unfortunately, after you have imported the WSDL using the Vs.net Wizard, you cannot successfully create an agent. So I have to convert the file generated by vs.net to WSDL after importing the original WSDL file:
Change the mode domain name space from Http://www.w3.org/1999/XMLSchema to Http://www.w3.org/2001/XMLSchema and then clear all the "q" domain names added by vs.net during the WSDL import.
Delete xmlns:tm=http://microsoft.com/wsdl/mime/textmatching/and xmlns:mime= "http://schemas.xmlsoap.org/wsdl/mime/" namespace, because this application does not need to include these.
Deletes a type element because the original WSDL document does not have the specified element section that contains schema information for the Web service.
Change the input Output element message property value to include the TNS namespace prefix in the form:
The following are the referenced contents: |
In the following these minor changes, VS. NET Wizard can read the WSDL and automatically generate an agent. After compiling the proxy, it is included in a ASP.net page. However, when this asp.net page is executed: "Message does not have a correct soap root XML tag." This error is returned as a SOAP error from the Web service.
To accurately evaluate this error, the proxy call is used by a utility named proxy Trace so that the agent generates the SOAP wrapper. This can be done by adding the following code into the ASP.net page:
Msnews.proxy = new System.Net.WebProxy (http://localhost:8080);
At the view of the. NET agent, I am a little surprised to see why this error is returned because in fact a relative soap wrapper is generated and sent to the Web service. This error persists even after several attempts have been made to convert the proxy code. Code Snippet Listing 2 shows the complete SOAP error wrapper returned from the PHP Web service.
After several unsuccessful attempts to link the asp.net pages to the PHP Web service using the proxy object created in Vs.net, I decided to create a soap wrapper from scratch to perform more efficient program debugging. {At first, it looked as if by. NET agent generated mode domain name space may be the key to the problem, because. NET uses the 2001 mode specification and the PHP service uses the 1999 version of the specification.
However, I changed the custom soap wrapper to version 1999 instead of the 2001 version, and the error persists. After experimenting with several other minor changes, I decided to change the namespace prefix and body elements used by the soap wrapper from soap (generated by the. NET proxy) to soap-env, because I saw that the soap-env prefix was returned in the SOAP error message. (See Code 2) This seemingly insignificant change solves the problem! When processing any request, the PHP service obviously needs to soap-env the prefix and reject the requirement that does not contain the soap-env prefix.
Create a custom Proxy
Now that you understand why the Web service returns a SOAP error, we can create a custom proxy soap wrapper for the next-life networking service. Although creating a custom soap wrapper will certainly take more time than using a soap wrapper generated by a vs.net or WSDL.exe utility, this can completely control the contents of the wrapper. To start creating a custom proxy, I create a new class named Msnewsserviceproxy that contains two fields:
The following are the referenced contents: public class Msnewsserviceproxy { String _uri; String _soapaction; } |
The URI field holds the location of the Web service, and the _soapaction field holds the name of the SOAPAction header that will be sent using the soap wrapper. Within the Msnewsserviceproxy class, add the three methods of Createsoapenvelope (), Sendsoapenvelope (), and Filterresult (). These methods generate a SOAP wrapper request, send it to a Web service, and then filter the returned SOAP wrapper. Let's look at each method individually. Note The code adds a soap-env namespace prefix to the root element of the soap wrapper. The Web service obviously needs this particular prefix and rejects any information that does not contain the prefix. Because the vs.net generated proxy sends a SOAP domain prefix (instead of soap-env), its message is rejected. Web services should not need a specific domain namespace prefix to reject messages without prefixes, but the domain name space problem is that you have to be careful to get the job done better, to perform something that looks {0> and incredible.
After the soap wrapper is created, the Sendsoapenvelope () method (see Code Snippet 4) uses a number of classes in the System.Net and System.IO domain namespace to send the wrapper to the Web service. The code first creates a HttpWebRequest object by passing the _uri variable to the object builder. Second, the corresponding Method,contenttype and headers associated with this request will be sent.
Then a StreamWriter object is associated with the request stream of the HttpWebRequest object, and the soap wrapper is written to the stream using the StreamWriter write () method.
The soap wrapper returned from the Web service is obtained by the Sendsoapenvelope () method of the HttpWebResponse object.
HttpWebResponse response = (HttpWebResponse) request. GetResponse ();
If the answer is not NULL, it is loaded into a xmltextreader,xmltextreader that is used to populate the XmlDocument object. The XmlDocument object is then returned from this method.
The Filtersoapenvelope () method analyzes the soap reply wrapper and loads the data returned from the Web service into the XmlDocument object used by the "consumer" of the Custom proxy:
The following are the referenced contents: Private XmlDocument Filtersoapenvelope ( XmlDocument Doc) { XmlDocument Filterdoc =new XmlDocument (); XmlNode result = Doc. selectSingleNode ("//results"); XmlNode Resultimport = Filterdoc.importnode (result,true); Filterdoc.appendchild (Resultimport); return filterdoc; } |
Although filters can be executed in several ways, the Filtersoapenvelope () method relies on XPath statements to get the result element in the reply soap wrapper.
The Microsoft Newsgroup PHP Web service shows two ways to allow a newsgroup news digest: Getheaders () and GetMessage (). You can see how to use both methods in the custom proxy class (see Code Snippet 5). Note The code passing Web service method name in each method is invoked to the Createsoapenvelope () method and any parameters associated with this method. After the soap wrapper is sent and the response is accepted, the Filtersoapenvelope () method is called to load the returned data into a XmlDocument object, which is also used by the proxy "consumer."