In what year did soap web services appear? Listing of the PersonServiceImpl class

With the evolution of the Internet, there has been a need to create distributed applications. Applications installed on a computer usually use the libraries located on it. Several programs can use one library. Can library analogs be posted on the Internet so that different sites can call them? It turns out, yes.

Enterprises on their pages provide a variety of information. For example, from its website http://www.Ford.com the Ford company publishes information about models and prices. The dealer of this company would like to have this information on his website as well. The web service allows a consumer site to retrieve information from a provider site. The consumer site displays this information on its pages. The code to generate this information is written once but can be used by many consumers. The data is presented in plain text, so it can be used regardless of the platform.

Web services are widely used in both Desktop and Internet applications. They are not applications themselves, but data sources for applications. They are missing user interface... Web services do not need to be used over the network — they can be part of the project in which they are used.

Web services are functionality and data provided for use by external applications that interact with services through standard protocols and data formats. Web services are completely language and platform independent. Web services technology is the cornerstone of Microsoft's programming model. NET.

it further development component programming CORBA and DCOM. However, in order to use such components, it is necessary to register them in the consumer's system. This is not required for web services. Components work well on local area networks. HTTP is not a remote procedure call (RPC) protocol. Even within the same organization, different OS that can only communicate over HTTP.

Several attempts have been made to create a communication language between heterogeneous systems - DCOM, CORBA, RMI, IIOP. They did not receive general distribution, since each of them was promoted by different manufacturers and therefore was tied to the technologies of a particular manufacturer. Nobody wanted to accept someone else's standard. To overcome this dilemma, several companies have agreed to develop a vendor-neutral standard for messaging over HTTP. In May 2000, IBM, Microsoft, HP, Lotus, SAP, UserLand and others approached the W3C and put forward SOAP as a candidate for such a standard. SOAP revolutionized application development by uniting two Internet standards, HTTP and XML.

SOAP

To interact with web services, the XML-based SOAP protocol is used. You could use just XML, but this is too loose format, in which each document actually creates its own language. SOAP is a convention about the format of an XML document, about the presence of certain elements and namespaces in it.

SOAP allows you to publish and consume complex data structures such as a DataSet. At the same time, it is easy to learn. Current version SOAP - 1.2.

SOAP stands for Simple Object Access Protocol. SOAP is designed to make it easier for applications to communicate over HTTP. It is a specific platform-independent messaging format over the Internet. A SOAP message is a regular XML document. Standard

Lyrical part.

Imagine that you have implemented or are being implemented a certain system that should be accessible from the outside. Those. there is a certain server with which you need to communicate. For example a web server.

This server can perform many actions, work with the database, perform some third-party requests to other servers, engage in some kind of calculations, etc. live and possibly develop according to his well-known scenario (i.e. according to the developers' scenario). A person is not interested in communicating with such a server, because he may not be able / willing to give beautiful pages with pictures and other user-friendly content. It is written and works in order to work and issue data to requests to it, without caring that they are human-readable, the client will deal with them himself.

Other systems, referring to this server, can already dispose of the data received from this server at their own discretion - to process, accumulate, issue to their clients, etc.

Well, one of the options for communicating with such servers is SOAP. SOAP xml messaging protocol.

The practical part.

A web service (this is what the server provides and what the clients use) makes it possible to communicate with the server in clearly structured messages. The fact is that the web service does not accept any data. Any message that does not comply with the rules will be answered by the web service with an error. The error will be, by the way, also in the form of xml with a clear structure (which is not true about the text of the message).

WSDL (Web Services Description Language). The rules by which messages for the web service are compiled are described in the same way with using xml and also have a clear structure. Those. if a web service provides the ability to call a method, it should let clients know what parameters are used for this method. If the web service expects a string for the Method1 method as a parameter and the string must be named Param1, then these rules will be specified in the web service description.

As parameters, not only simple types can be passed, but also objects, collections of objects. The description of the object is reduced to the description of each component of the object. If an object consists of several fields, then each field is described what type, name (what possible values). Fields can also be of a complex type, and so on until the description of types ends with simple ones - string, boolean, number, date ... However, some specific types may turn out to be simple, it is important that clients can understand what values ​​may be contained in them.

For clients, it is enough to know the url of the web service, wsdl will always be there, by which you can get an idea of ​​the methods and their parameters that this web service provides.

What are the advantages of all these bells and whistles:

  • In most systems, the description of methods and types occurs in automatic mode... Those. it is enough for the programmer on the server to say that this method can be called through a web service, and the wsdl description will be generated automatically.
  • A well-structured description is readable by any soap client. Those. whatever the web service, the client will understand what data the web service is accepting. According to this description, the client can build his own internal structure of object classes, the so-called. binding "and. As a result, the programmer using the web service has to write something like (pseudocode):

    NewUser: = TSoapUser.Create ("Vasya", "Pupkin", "odmin"); soap.AddUser (NewUser);

  • Automatic validation.

    • xml validation. xml must be well-formed. invalid xml - immediately an error to the client, let him figure it out.
    • schema validation. xml must have a specific structure. xml does not correspond to the scheme - immediately an error to the client, let him understand.
    • data validation is performed by the soap-server so that data types, restrictions correspond to the description.
  • Authorization and authentication can be implemented separate method... natively. or using http authorization.
  • Web services can work both over the soap protocol and over http, that is, through get requests. That is, if the parameters are simple data (no structure), then you can simply call the usual get www.site.com/users.asmx/GetUser?Name=Vasia or post. However, this is not everywhere and not always.
  • ... see wikipedia

There are also plenty of cons:

  • Unreasonably large message size. Well, here the very nature of xml is such that the format is redundant, the more tags, the more useless information. Plus, soap adds its own redundancy. For intranet systems, the traffic issue is less acute than for the internet, so soap for local area networks more in demand, in particular, Sharepoint has a soap web service with which you can successfully (and with some restrictions) communicate.
  • Automatically changing the description of a web service can break all clients. Well, it's like for any system, if backward compatibility with old methods is not supported, everything will fall off ...
  • Not a minus, but a disadvantage. All actions for calling methods must be atomic. For example, working with a subdivision, we can start a transaction, execute several requests, then rollback or commit. There are no transactions in soap. One request, one response, the conversation is over.
  • It can be quite difficult to understand the description of what is on the server side (is everything described correctly by me?), What is on the client (what was written to me here?). There were several times when I had to deal with the client side, and convince the server programmer that his data was incorrectly described, and he could not understand anything at all, because automatic generation and he, as it were, should not, this is a software business. And the error was naturally in the code of the method, the programmer simply did not see it.
  • Practice shows that the developers of web services are terribly far from the people using these web services. In response to any request (valid from the outside), an unintelligible error "Error 5. Everything is bad" may come. It all depends on the conscience of the developers :)
  • I probably still haven't remembered something ...

As an example, there is the open web service belavia:

  • http://86.57.245.235/TimeTable/Service.asmx - entry point, there is also a text description of methods for third-party developers.
  • http://86.57.245.235/TimeTable/Service.asmx?WSDL - wsdl description of methods and types of received and returned data.
  • http://86.57.245.235/TimeTable/Service.asmx?op=GetAirportsList - a description of a specific method with an example of an xml request and an xml response.

You can manually create and send a request like:

POST /TimeTable/Service.asmx HTTP / 1.1 Host: 86.57.245.235 Content-Type: text / xml; charset = utf-8 Content-Length: length SOAPAction: "http://webservices.belavia.by/GetAirportsList" ru

the answer will come:

HTTP / 1.1 200 OK Date: Mon, 30 Sep 2013 00:06:44 GMT Server: Microsoft-IIS / 6.0 X-Powered-By: ASP.NET X-AspNet-Version: 4.0.30319 Cache-Control: private, max -age = 0 Content-Type: text / xml; charset = utf-8 Content-Length: 2940

Shl Earlier, the Aeroflot web service was opened, but after 1C added soap support to 8k, a bunch of 1c beta testers successfully put it down. Now something has changed there (I don’t know the addresses, you can search if interested).
ZZY Disclaimer. He told me at the household level. You can kick.

Disclaimer:A lot of articles on this topic have been written and, as you, of course, guessed, this is the next one. Perhaps you will learn something new from it, but nothing super-secret that you could not Google yourself is not described here. Only notes from personal experience.

Introduction

We will only consider the situation when there is a third-party web service and the task is to establish data exchange.

The structure of the service is described in the file WSDL(English Web Services Description Language)

The file is most often available from the link where the entry point to the web service itself is located. I wrote "most often" as there are exceptions. For example, a SAP-based web service does not publish the wsdl and can only be obtained by unloading it from the application itself.

And so, we have a description of the web service, login, password. Let's get connected.

// Define the URLServiceNameSpace settings = "http://Somesite.ru"; UserName = "TestUser"; Password = "q1w2e3"; LocationWSDL = "https://Somesite.ru/WebService/Some?wsdl"; ServiceName = "SomeServiceName"; ConnectionPointName = "SomeService_Port"; // Create SSL Connection = New SecureConnection OpenSSL (); WSDefinition = New WSDefinition (LocationWSDL, SSL); WSProxy = New WSProxy (WSDefinition, ServiceNameSpace URL, ServiceName, ConnectionPointName, SSL); WSProxy.User = UserName; WSProxy.Password = Password;

Fine! We have connected to the web service! In theory, this is the basis of any exchange option, since it allows you to create data structure object based on wsdl, and working with such an object is a pleasure.

Consider the XML that SoapUI gives us

357 121212 M 19900111 Mercedes GLS Audi TT

Now let's describe it programmatically

// Create an object and fill it with data XDTOFactory = WSDefinition.XDTOFactory; RootType = CustomXDTO.Type (ServiceNameSpace URL, "SUBMISSION"); RootObject = MyXDTOFactory.Create (RootType); RootObject.ID = "4356"; ClientType = CustomXDTO.Type (ServiceNameSpace URL, "CUSTOMER"); ClientObject = OwnXDTOFactory.Create (ClientType); ClientObject.CLIENT_ID = "121212"; ClientObject.SEX = "M"; // F - female, M - male ClientObject.CLIENT_BIRTHDAY = "19900111"; // Client cars AutoType = OwnFactoryXDTO.Type (URLServiceNameSpace, "CARS"); AutoObject = OwnXDTOFactory.Create (AutoType); AutoObject.CLASS = "Mercedes"; AutoObject.MODEL = "GLS"; ClientObject.CARS.Add (AutoObject); AutoObject = OwnXDTOFactory.Create (AutoType); AutoObject.CLASS = "Audi"; AutoObject.MODEL = "TT"; ClientObject.CARS.Add (AutoObject); RootObject.CUSTOMER.Add (ClientObject);

The data has been filled in successfully. Now you need to send them.

At this very moment, many nuances arise. Let's try to consider each.

Recipe 1. Sending the entire XDTO object

Result = WSProxy.AddCustomers (RootObject);

It remains only to process the result that the service returned to us and that's it. Agree that this is very convenient!

But in practice, this is not always the case. For example 1c does not get along with prefixing certain tags inside xml when the namespace of the root tag is different from that of the children. In such cases, you have to collect soap manually. I also had to deal with web services that wait for pure xml as a parameter. Insanity, but still this is not too difficult.

Recipe 2. Sending clean xml as a parameter

XMLWriteParameters = New XMLWriterParameters ("UTF-8", "1.0", True); MyXML = New XML Record; MyXML.SetString (XMLWriter Options); MyXML.WriteXMLDeclaration (); MyXDTOFactory.WriteXML (MyXML, RootObject); XML String = MyXML.Close (); If DeleteNamespaceDescription Then Attempt FirstTagVSRow = StrGetString (XMLString, 2); RootTagName = RootObject.Type (). Name; XMLString = StringReplace (XMLString, FirstTagVS string, "<"+ИмяКорневогоТэга+">"); Exception // DescriptionErrors () EndTry; EndIf; Result = WSProxy.AddCustomers (XML String);

If you do not remove the namespace that 1c adds by default, then it has become more than 5 lines of code. More often than not, I wrap the xml conversion in a function, since I usually call more than one method.

Recipe 3. Sending a Native HTTP Request.

StringSOAP = " | | | "+ XML String +" | |"; // Describe the headers of the HTTP request Headers = New Match; Headers.Insert (" Content-Type "," text / xml; charset = UTF-8 "); Headers.Insert (" SOAPAction "," http: // sap.com/xi/WebService/soap1.1 "); Headers.Insert (" Authorization "," Basic "+ GetBase64AuthorizationHeader (Username, Password)); // ATTENTION !!! // You cannot programmatically fill in the following headers, because this leads to an error // The platform will fill them in correctly // Headers. ЧГ = ")); // message length // Headers. Insert ("Host", "Somesite.ru:8001"); // Headers. Insert ("Connection "," Keep-Alive "); // Headers. Insert ("User-Agent", "Apache-HttpClient / 4.1.1 (java 1.5)"); // Connect to the site. Connection = New HTTPConnection ("Somesite.ru/WebService/Some", Username, Password, SSL, False); // The address must be without https: // // Get the text of the root page through a POST request. HTTP Request c = New HTTPRequest ("/ GetCustomer", Headers); HTTPRequest.SetBodyFromString (StringSOAP); Result = Connection.CallHTTPMethod ("POST", HTTPRequest);

In this case, we will have to collect soap manually. In fact, we just wrap the xml from recipe 2 in a soap shell, where, depending on the requirements of the web service, we can change our soap as we like.

Next, we describe the headers according to the documentation. Some services will calmly chew our request without headers, here you need to look at a specific case. If you do not know what headers to write, then the easiest way is to spy on the request in SoapUI by switching to the RAW tab.

The function for getting Base64 string looks like this (spied on):

Function GetBase64AuthorizationHeader (UserName, Password) FileCoding = TextCode.UTF8; TemporaryFile = GetTemporaryFileName (); Record = New Text Record (TemporaryFile, FileCode); Record.Record (Username + ":" + Password); Record.Close (); DWData = New BinaryData (TemporaryFile); Result = Base64String (DWData); DeleteFiles (TemporaryFile); Result = Avg (Result, 5); Refund Result; EndFunction

There is an important point. When working with HTTPConnection, specify the address without specifying the "http: //" and "https: //" protocols, otherwise you risk wasting time looking for an obvious error.

Recipe 4. Sending via WinHttpRequest

WinHttp = New COMObject ("WinHttp.WinHttpRequest.5.1"); WinHttp.Option (2, "UTF-8"); WinHttp.Option (4, 13056); // intSslErrorIgnoreFlag WinHttp.Option (6, true); // blnEnableRedirects WinHttp.Option (12, true); // blnEnableHttpsToHttpRedirects WinHttp.Open ("POST", "https://Somesite.ru/WebService/Some/GetCustomer", 0); WinHttp.SetRequestHeader ("Content-type", "text / xml"); WinHttp.SetCredentials (UserName, Password, 0); WinHttp.Send (String SOAP); WinHttp.WaitForResponse (15); XMLResponse = WinHttp.ResponseText ();

Here, in essence, the same as in the previous version, but we work with a COM object. We indicate the connection string in full, along with the protocol. Special attention should only be paid to the ignore SSL certificate error flags. They are needed if we work on SSL, but without a specific certificate, since it is not possible to create a new secure connection in this option (or I don’t know how). The rest of the mechanism is similar to the previous one.

Also, in addition to "WinHttp.WinHttpRequest.5.1", you can use "Microsoft.XMLHTTP", "Msxml2.XMLHTTP", "Msxml2.XMLHTTP.3.0", "Msxml2.XMLHTTP.6.0", if suddenly it does not take off on WinHttp. The methods are almost the same, only the number of parameters is different. I suspect that one of these options is hardcoded inside the 1c HTTPRequest object.

At the moment, these are all the recipes that I have. If I come across new ones, I will definitely supplement the article.

Processing the result

In Recipe 1, we most often get a ready-made XDTO object and work with it as with a structure. In all other cases, you can convert the xml response into an XDTO

If Result.StatusCode = 200 Then XMLReader = New XMLReader; ReadXML.SetString (Result.GetBodyAsString ()); ObjectResponse = OwnXDTOFactory.ReadXML (ReadXML); Report (ObjectResponse.Body.Response.RESPONSE_ID); Report (ObjectResponse.Body.Response.RESPONSE_TEXT); EndIf;

Everything is simple here.

Instead of a conclusion

1. Start working with web services with the SoapUI program. It is designed for such work and will allow you to quickly understand how a particular service works. There is an article for mastering

2. If you exchange with the service via an unsecured http channel and the question arises as to what exactly 1c sends in your messages, then you can use traffic sniffers such as Wireshark, Fiddler, and others. The problem will only arise if you are using an ssl connection.

3. If, nevertheless, the web service communicates via https, then we put on the remote machine (any, the main thing is not on our own) the Nginx server, to which we will contact, and it, in turn, will pack everything in https and send it where necessary ( reverse proxy ) and add to the standard config:

Server (listen 0.0.0.0:8080; server_name MyServer; location ~. * (Proxy_pass https://Somesite.ru:8001; proxy_set_header Host $ host; proxy_set_header Authorization "Basic "; proxy_pass_header Authorization;))

5. If authentication involves the use of cookies, then the following was found

P.S. If you have questions, suggestions for improving the code, have your own recipes that are different from those described, you found errors or think that the author is "nippy" and he "has no place in 1c", then write comments and we will discuss everything.

The topic title is really a question, since I myself do not know what it is and for the first time I will try to work with it within the framework of this article. The only thing I can guarantee that the code below will work, but my phrases will be just assumptions and guesses about how I myself understand all this. So let's go ...

Introduction

We need to start with what the concept of web services was created for. By the time this concept appeared, technologies already existed in the world that allowed applications to interact at a distance, where one program could call some method in another program, which at the same time could be launched on a computer located in another city or even a country. All of this is abbreviated as RPC (Remote Procedure Calling). Examples include CORBA technologies, and for Java - RMI (Remote Method Invoking). And everything seems to be good in them, especially in CORBA, tk. you can work with it in any programming language, but something was still missing. I believe that the disadvantage of CORBA is that it works through some of its own network protocols instead of simple HTTP, which will crawl through any firewall. The idea behind the web service was to create an RPC that would stick into HTTP packets. This is how the development of the standard began. What are the basic concepts of this standard:
  1. SOAP... Before calling a remote procedure, you need to describe this call in XML file e SOAP format. SOAP is simply one of the many XML markups used in web services. Everything that we want to send somewhere via HTTP is first turned into an XML SOAP description, then it is put into an HTTP packet and sent to another computer on the network via TCP / IP.
  2. WSDL... There is a web service i.e. a program whose methods can be called remotely. But the standard requires that a description be attached to this program, which says that "yes, you are not mistaken - this is really a web service and you can call such and such methods from it." This description is represented by another XML file that has a different format, namely WSDL. Those. WSDL is just an XML description file for a web service and nothing else.
Why do you ask so briefly? Can't you get more details? Probably you can, but for this you have to turn to books like Mashnin T. "Java Web Services". There for the first 200 pages goes detailed description each tag of SOAP and WSDL standards. Should I do it? In my opinion, no, tk. all of this is generated automatically in Java, and all you need to do is write the contents of the methods that are supposed to be called remotely. So, in Java there was such an API as JAX-RPC. If anyone does not know, when they say that Java has such and such an API, it means that there is a package with a set of classes that encapsulate the technology in question. JAX-RPC evolved from version to version for a long time and eventually evolved into JAX-WS. WS obviously stands for WebService and you might think that this is a simple renaming of RPC into a popular word these days. This is not the case, since Now web services have moved away from the original idea and allow you not only to call remote methods, but also to simply send document messages in SOAP format. Why this is needed, I do not know yet, the answer is unlikely to be "just in case, suddenly it will be needed." I myself would like to learn from more experienced comrades. And the last thing, then there was also JAX-RS for the so-called RESTful web services, but this is a topic for a separate article. At this point, the introduction can be ended, because next we will learn to work with JAX-WS.

General approach

Web services always have a client and a server. The server is our web service and is sometimes called an endpoint (like the endpoint where SOAP messages from the client go). We need to do the following:
  1. Describe the interface of our web service
  2. Implement this interface
  3. Start our web service
  4. Write a client and call the required web service method remotely
The web service can be started different ways: either declare a class with a main method and run the web service directly as a server, or deploy it to a server like Tomcat or whatever. In the second case, we ourselves do not run new server and do not open another port on the computer, but simply tell the Tomcat servlet container that "we wrote the web service classes here, publish them, please, so that everyone who contacts you can use our web service." Regardless of the method of launching the web service, we will have the same client.

Server

Let's start IDEA and create new project Create New Project... Let's enter a name HelloWebService and press the button Next, then the button Finish... In folder src create a package ru.javarush.ws... In this package, we will create the HelloWebService interface: package ru. javarush. ws; // these are annotations, i.e. a way to mark our classes and methods, // as related to web service technology import javax. jws. WebMethod; import javax. jws. WebService; import javax. jws. soap. SOAPBinding; // we say that our interface will work as a web service@WebService // say that the web service will be used to call methods@SOAPBinding (style = SOAPBinding. Style. RPC) public interface HelloWebService ( // we say that this method can be called remotely@WebMethod public String getHelloString (String name); ) In this code, the WebService and WebMethod classes are so-called annotations and do nothing but mark our interface and its method as a web service. The same is true for the SOAPBinding class. The only difference is that SOAPBinding is a parameter annotation. V in this case the style parameter is used with a value that says that the web service will work not through document messages, but like a classic RPC, i.e. to call the method. Let's implement the logic of our interface and create a HelloWebServiceImpl class in our package. By the way, I note that the end of the class in Impl is a convention in Java, according to which the implementation of interfaces is denoted in this way (Impl - from the word implementation, i.e. implementation). This is not a requirement and you are free to name the class whatever you want, but the rules of good form require it: package ru. javarush. ws; // the same annotation as when describing the interface, import javax. jws. WebService; // but used here with endpointInterface parameter, // specifying the fully qualified class name of the interface of our web service@WebService (endpointInterface = "ru.javarush.ws.HelloWebService") public class HelloWebServiceImpl implements HelloWebService (@Override public String getHelloString (String name) ( // just return a greeting return "Hello," + name + "!" ; )) Let's start our web service as an independent server, i.e. without the involvement of any Tomcat and application servers (this is a topic for a separate discussion). To do this, in the project structure in the folder src let's create a package ru.javarush.endpoint, and in it create a HelloWebServicePublisher class with a main method: package ru. javarush. endpoint; // class to start a web server with web services import javax. xml. ws. Endpoint; // class of our web service import ru. javarush. ws. HelloWebServiceImpl; public class HelloWebServicePublisher (public static void main (String... args) ( // start the web server on port 1986 // and at the address specified in the first argument, // start the web service passed in the second argument Endpoint. publish ( "http: // localhost: 1986 / wss / hello", new HelloWebServiceImpl ()); )) Now let's run this class by clicking Shift + F10... Nothing appears in the console, but the server is running. You can verify this by typing in the browser the line http: // localhost: 1986 / wss / hello? Wsdl. The page that opens, on the one hand, proves that a web server (http: //) has started on our computer (localhost) on port 1986, and, on the other hand, shows the WSDL description of our web service. If you stop the application, the description will become inaccessible, as well as the web service itself, so we will not do this, but proceed to writing the client.

Customer

In the project folder src create a package ru.javarush.client, and in it the HelloWebServiceClient class with the main method: package ru. javarush. client; // needed to get wsdl description and through it // reach the web service itself import java. net. URL; // such an execution will occur when working with a URL object import java. net. MalformedURLException; // classes to parse xml-ku with wsdl description // and reach the service tag in it import javax. xml. namespace. QName; import javax. xml. ws. Service; // the interface of our web service (we need more) import ru. javarush. ws. HelloWebService; public class HelloWebServiceClient (public static void main (String args) throws MalformedURLException ( // create a link to wsdl description Url url= new URL ( "http: // localhost: 1986 / wss / hello? wsdl") ; // We look at the parameters of the next constructor in the very first tag of the WSDL description - definitions // see the 1st argument in the targetNamespace attribute // see the 2nd argument in the name attribute QName qname = new QName ("http: //ws.site/", "HelloWebServiceImplService"); // Now we can reach the service tag in the wsdl description, Service service= Service. create (url, qname); // and then up to the nested port tag, so that // get a link to a web service object remote from us HelloWebService hello = service. getPort (HelloWebService. class); // Hooray! Now you can call the remote method System. out. println (hello. getHelloString ("CodeGym")); )) I gave maximum comments on the code in the listing. I have nothing to add, so run (Shift + F10). We should see the text in the console: Hello, CodeGym! If you didn't see it, you probably forgot to start the web service.

Conclusion

In this topic, a brief excursion into web services was presented. Again, a lot of what I've written is my guesswork as to how it works, and therefore shouldn't be trusted too much. I would be grateful if knowledgeable people they will correct me, because then I will learn something. UPD.

Alexey Boyko

SOAP and XML Web Services on the .Net Platform

XML Web Services offer this level of compatibility and interoperability across operating systems,

platforms and languages ​​that were previously simply not available.

Andrew Troelsen (MVP (Most Valuable Professional in Microsoft))

If you haven’t worked with XML web services yet, you’ve probably heard the word “SOAP”. It's time to get to grips with these concepts.

Intro

If you are interested in the Internet or smaller networks, chances are you will sooner or later come across XML Web Services. An XML web service is not only a web application that can output information to a browser. Rather, it is a remoting technology that allows methods and properties of an object over the network to be invoked using standard HTTP requests.

In practice, this means that the clients of such a service can be written in different languages ​​and for different operating systems.

As an information "transport" between the service and the client, you can use the HTTP GET or POST methods.

And you can "overlay" one more protocol - SOAP (Simple Object Access Protocol). This is usually done, since in this case it is possible to pass complex types (including user-defined ones). And the classic GET and POST methods only support lists, simple arrays, and strings.

Example SOAP Interop

A SOAP message is an XML document wrapped in the body of an HTTP request.

Listing 1. Structure of a SOAP message

The interaction between the client and the service is as follows:

  • the client creates a SOAP request and sends it to the service;
  • service on remote computer executes the procedure and sends a SOAP response.

For example, a SOAP request might look like this, calling the HelloWorld () method of a remote XML web service:

Listing 2. An example SOAP request

The HelloWorld () method, as expected, returns the string "Hello world!":

Listing 3. Sample SOAP response

Xmlns: xsi = "http://www.w3.org/2001/XMLSchema-instance" xmlns: xsd = "http://www.w3.org/2001/XMLSchema">

Hello world!

Creating an XML Web Service in .NET 2.0

You can create a service different ways, we will use Visual Studio 2005. Click "File -> New -> Web Site", in the opened window select "ASP.NET web Service". At the address specified during creation, you will find the following files and directories (see Fig. 1).

In principle, a service can contain only one single file with the * .asmx extension. (The extension * .asmx is used to denote .Net web services.) In this case, this is not the case, look at the contents of the Service.asmx file:

Listing 4. Service.asmx defines external file support

<%@ WebService Language="C#" CodeBehind="~/App_Code/Service.cs" class="Service" %>

The CodeBehind attribute specifies an external file located in the App_Code folder that contains the code that implements the HelloWorld () method:

Listing 5. Service.cs File Implementing HelloWorld () Method

using System;

using System.Web;

using System.Web.Services;

Public Service () (

Return "Hello World";

It is possible to create a single Service.asmx file, without support code, that has the same functionality:

Listing 6. Service.asmx without external support code

<%@ WebService Language="C#" class="Service" %>

using System;

using System.Web;

using System.Web.Services;

using System.Web.Services.Protocols;

public class Service: System.Web.Services.WebService

Public Service () (

Public string HelloWorld () (

Return "Hello World";

We don't need this, and we will not do that.

As you can see, the only method in our web service is tagged with an attribute that informs the ASP.NET runtime that this method is available for incoming HTTP requests. Members not identified with this attribute will not be available to client programs.

Such a simple service is quite suitable for our experiments, it remains only to publish it.

Publishing XML Web Service Using IIS

We are not talking about publishing on the Internet, but about creating conditions for testing our service on a local computer.

The first step is to install IIS (Internet Information Server). To do this, open the "Add or Remove Programs" window and select "Install Windows components". (Some Windows versions do not involve an IIS installation such as Windows XP Home Edition.)

Note: IIS server it is better to install earlier than the .Net Framework, otherwise you will have to configure IIS to support .Net applications by running the utility command line aspnet_regiis.exe (with the / i flag).

Create a virtual directory. If you are using Windows XP Pro, go to "Control Panel -> Administrative Tools -> Internet Information Services". In the window that opens, select Action -> Create -> Virtual Directory.

The New Virtual Directory Wizard will start. Alias ​​Soap1 and specify the path to the directory where you want to place the service, for example C: \ Soap1. Now copy the contents of our web service there.

Type http: //localhost/soap1/Service.asmx in the address bar of your browser, and you should see the service testing page (see Figure 2).

Viewing SOAP Messages

The test page does not allow sending and reading SOAP messages. For this reason, you will have to use third-party development, I recommend using soapUI. (This is a free product available at http://www.soapui.org.)

After installing soapUI, create a new project called soap1, leaving the Initial WSDL field empty (see Figure 3).

Right click on the newly created project and select "Add WSDL from URL". In the dialog box that opens, enter http: //localhost/soap1/Service.asmx? Wsdl. We now have the ability to send SOAP requests to our service and view the responses received. (Requests will be generated by soapUI automatically.)

What is this WSDL? The WSDL document describes how clients interact with a web service. It describes what service methods are available for external invocation, what parameters they accept and what they return, as well as other information required for remoting. Such a document can be compiled manually, or you can entrust its generation to the server, for this it is enough to add the? Wsdl suffix to the URL pointing to the * .asmx file.

To view the WSDL document for our service, enter http: //localhost/soap1/Service.asmx? Wsdl in your browser. The information from this document is used by soapUI to automatically generate SOAP requests.

SOAP Extensions

As you may have noticed, creating an XML web service (as well as a client) does not need to be concerned with the appearance of the SOAP messages. It is enough to mark the required methods with an attribute, and the ASP.NET runtime generates packages of the required format.

In fig. 4 shows the request and response of the web service received using the soapUI program.

Let's do it one more time. The request is generated by soapUI - when creating real clients for the service, you also do not need to manually format the SOAP packets. We also did not directly participate in the creation of the service response. All this happens automatically.

However, it is likely that you will need to modify these packages yourself. For example, compress or encrypt the transmitted data. This is the purpose of SOAP Extensions.

SOAP Extensions is a mechanism that allows you to arbitrarily modify the SOAP messages you send and receive.

SOAP message "path"

To get started with programming, you need to consider the path that a SOAP message takes before it is received and processed by the appropriate method (see Figure 5).

A SOAP message can be thought of as an XML document describing an object transmitted over a network. Before using the object passed in this way, it must be restored (or, if you prefer, assembled) from this description. The XML serializer serves this purpose.

Incoming packets are deserialized (restoring an object from an XML description), and sent ones are serialized (creating an XML description of an object).

In fig. 5 shows four points (BeforeSerialize, AfterDeserialize, BeforeDeserialize, AfterSerialize) at which we can intercept a SOAP message using SOAP Extensions. Modify it and send it further.

SOAP Extension Implementation

To begin with, let's define a task: let's say we want to modify the SOAP packets sent by the web service as shown in Listing 7:

Listing 7. Old and new XML web service responses

Xmlns: xsi = "http://www.w3.org/2001/XMLSchema-instance" xmlns: xsd = "http://www.w3.org/2001/XMLSchema">

Hello world

Xmlns: xsi = "http://www.w3.org/2001/XMLSchema-instance" xmlns: xsd = "http://www.w3.org/2001/XMLSchema">

Cipher text

Action plan for implementing SOAP Extension:

  • Create a dll with a class inherited from SoapExtension.
  • Add the bin folder to our web service and put the created dll there.
  • Add the web.config file to the service and make the necessary changes to it.

We'll discuss the role of the bin folder and web.config file later.

Creating DLL with SOAP Extension

Create a new "Class Library" project called SoapExtensionLib. In this project, we only need to implement one class that will perform the modifications we need to the SOAP packages. This class must inherit from the SoapExtension class.

Listing 8. Creating a class inheriting from SoapExtension

using System;

using System.Web.Services;

using System.Web.Services.Protocols;

using System.IO;

using System.Net;

using System.Xml;

Each SOAP Extension receives as a parameter a stream containing the object to be passed over the network (before or after serialization). And it must return a stream.

The SOAP Extension can be thought of as a "box" that can be placed at one or all of the four points (BeforeSerialize, AfterDeserialize, BeforeDeserialize, AfterSerialize) shown in Fig. 5. At each point there can be any number of such "inserts" (see Fig. 6).

The ChainStream method is used to receive these streams.

Listing 9. Implementing the ChainStream Method

public class TraceExtension: SoapExtension

Stream wireStream;

Stream appStream;

// method as an input parameter

// gets a stream containing the passed object

Public override Stream ChainStream (Stream stream)

WireStream = stream;

AppStream = new MemoryStream ();

Return appStream;

At BeforeDeserialize, the wireStream contains the received SOAP request from the network. This SOAP request needs to be passed to the application stream (appStream).

And at the point of AfterSerialize, you need to send the SOAP response sent to the network to the wireStream, which will be placed in the appStream.

To work with threads at each of the four points, you need to implement the ProcessMessage method.

Listing 10. Implementation of the ProcessMessage method that does not modify SOAP messages

// ProcessMessage doing the mandatory copy

// streams at two points (BeforeDeserialize and AfterSerialize)

Switch (message.Stage)

// at the point BeforeDeserialize you must pass

// SOAP request from the network stream (wireStream)

// to the application stream (appStream)

Case SoapMessageStage.BeforeDeserialize:

Copy (wireStream, appStream);

AppStream.Position = 0;

Break;

// at the point AfterSerialize must be passed

// SOAP response from application stream to network stream

AppStream.Position = 0;

Break;

void Copy (Stream from, Stream to)

TextReader reader = new StreamReader (from);

TextWriter writer = new StreamWriter (to);

Writer.WriteLine (reader.ReadToEnd ());

Writer.Flush ();

Think of Listing 10 as a blank for further experimentation. This implementation of the ProcessMessage method does not make any sense - the outgoing SOAP response is not modified in any way. Let's fix this:

Listing 11. Implementing the ProcessMessage Method to Modify the SOAP Response

public override void ProcessMessage (SoapMessage message)

Switch (message.Stage)

Case SoapMessageStage.AfterSerialize:

WriteOutput (message);

Break;

// some of the code was cut to save space

// rewrite the SOAP response

public void WriteOutput (SoapMessage message)

AppStream.Position = 0;

// create an XML document from the stream

XmlDocument document = new XmlDocument ();

Document.Load (appStream);

// To use XPath you need to define

// NamespaceManager

XmlNamespaceManager nsmgr = new XmlNamespaceManager (document.NameTable);

Nsmgr.AddNamespace ("soap", "http://schemas.xmlsoap.org/soap/envelope/");

XmlNode ResultNode = document.SelectSingleNode ("// soap: Body", nsmgr);

// replace the contents of the node

ResultNode.InnerText = "ciphertext";

// clean up the stream and write a new SOAP response to it

AppStream.SetLength (0);

AppStream.Position = 0;

Document.Save (appStream);

// MANDATORY ACTION

// pass the SOAP response from the application stream (appStream)

// into the network stream (wireStream)

AppStream.Position = 0;

Copy (appStream, wireStream);

Next, you need to define two methods (one of which is overloaded, that is, it can be called with different sets of parameters), which in our case are not needed. However, we must define them in accordance with the rules of inheritance from the SoapExtension class.

Listing 12. Other Required Methods

// In accordance with the rules of inheritance, we must

// define these methods, but we don't use them in any way

public override object?

GetInitializer (LogicalMethodInfo methodInfo, SoapExtensionAttribute attribute)

Return null;

public override object GetInitializer (Type WebServiceType)

Return null;

public override void Initialize (object initializer)

Return;

That's it, we compile the project. Finally we got a dll with SOAP Extension. The complete listing of SoapExtensionLib.dll can be found on the magazine website in the "Source Code" section.

Configuring a Web Service to Work with SOAP Extension

Open our XML web service project again with Visual Studio. Click "WebSite -> Add Reference" and select the SoapExtensionLib.dll you created earlier.

The Bin folder will be automatically added to the project. The * .dll files located in the Bin folder are automatically referenced by the application.

Now put the following content in the Web.Config file in the web service directory:

Listing 13. The Web.Config File

Priority = "1"

Group = "0" />

Now the structure of our service looks like the one shown in Fig. 7.

We use the Web.Config file to inform the ASP.NET framework that we have added the XML Soap Extension to the web service, which is implemented in the TraceExtension class located in the SoapExtensionLi.dll file.

Listing 14. The webServices Section in the Web.Config File

Priority = "1"

Group = "0" />

As you already know, many SOAP Extensions can be made, and the stream carrying the passed object (before or after serialization) will go through each of them. The order in which the stream flows through the various SOAP Extensions is specified using the priority and group attributes.

It is worth noting that by configuring Web.Config in this way, we inform the environment that our SOAP Extension will be called for each method of the service marked with the attribute. It is possible to create your own attribute and mark with it only those methods for which you need to call the SOAP Extension.

Listing 15. An example of using a custom attribute

public string HelloWorld () (

Return "Hello World";

To do this, add a class inherited from SoapExtensionAttribute to SoapExtensionLi.dll (see Figure 8).

Conclusion

This article reflects the main points of the construction and operation of XML web services on the .Net platform. I hope that the material presented will be quite enough so that, if necessary, you can engage in a deeper study of the topic.


In contact with