Disclaimer:A lot of articles have been written on this topic and, as you, of course, guessed, this is another one. You may learn something new from it, but nothing top-secret that you couldn’t google yourself is 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 via a link where the entry point to the web service itself is located. I wrote “most often” because there are exceptions. For example, a SAP-based Web service does not publish 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 connect.

// Define the settings of the ServiceNameSpace URL = "http://Somesite.ru"; UserName = "TestUser"; Password = "q1w2e3"; LocationWSDL = "https://Somesite.ru/WebService/Some?wsdl"; ServiceName = "SomeServiceName"; ConnectionPointName = "SomeService_Port"; // Create an SSL connection = New SecureConnectionOpenSSL(); WSDefinition = New WSDefinition(WSDLLocation,SSL); WSProxy = New WSProxy(WSDefinition, ServiceNameSpaceURL, ServiceName, ConnectionPointName, SSL); WSProxy.User = UserName; WSProxy.Password = Password;

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

Let's look at 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 Own FactoryXDTO = WS Definition. FactoryXDTO; RootType = OwnFactoryXDTO.Type(URLServiceNameSpace, "SUBMISSION"); RootObject = OwnFactoryXDTO.Create(RootType); RootObject.ID = "4356"; ClientType = OwnFactoryXDTO.Type(URLServiceNameSpace, "CUSTOMER"); ClientObject = OwnFactoryXDTO.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 = OwnFactoryXDTO.Create(AutoType); AutoObject.CLASS = "Mercedes"; AutoObject.MODEL = "GLS"; ClientObject.CARS.Add(AutoObject); AutoObject = OwnFactoryXDTO.Create(AutoType); AutoObject.CLASS = "Audi"; AutoObject.MODEL = "TT"; ClientObject.CARS.Add(AutoObject); RootObject.CUSTOMER.Add(CustomerObject);

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

At this very moment, many nuances arise. Let's try to look at each one.

Recipe 1. Send the entire XDTO object

Result = WSProxy.AddCustomers(RootObject);

All that remains is to process the result that the service returned to us and that’s all. Agree that this is very convenient!

But in practice this is not always the case. For example, 1C does not get along with the prefixation of certain tags inside xml, when the namespace of the root tag differs from the space of the child tags. In such cases, you have to collect the soap manually. I also had to deal with web services that expect pure xml as a parameter. It's insanity, but it's still not too difficult to do.

Recipe 2. Send pure xml as a parameter

XMLRecordParameters = NewXMLRecordParameters("UTF-8", "1.0", True); MyXML = NewXMLRecord; MyXML.SetString(XMLRecordParameters); MyXML.WriteXMLDeclaration(); OwnFactoryXDTO.WriteXML(MyXML, RootObject); StringXML = MyXML.Close(); If RemoveNameSpaceDescription Then TryFirstTagInRow = StrGetRow(XMLString,2); RootTagName = RootObject.Type().Name; XMLString = StrReplace(XMLString, FirstTagInString, "<"+ИмяКорневогоТэга+">"); Exception //ErrorDescription() EndAttempt; EndIf; Result = WSProxy.AddCustomers(XML String);

If you do not delete the namespace that 1c adds by default, then there are only 5 more lines of code. Most often I wrap the xml transformation in a function since we usually call more than one method.

Recipe 3. Send via native HTTPRequest.

String SOAP = " | | |" +XMLString+ " | |"; // 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 itself will fill them in correctly //Headers.Insert("Accept-Encoding", "gzip,deflate"); //Headers.Insert("Content-Length", Format(StringLength(SOAPString)," CHG=")); // 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:// // We receive the text of the root page via a POST request. HTTPRequest = New HTTPRequest("/GetCustomer", Headers); HTTPRequest.SetBodyFromString(StringSOAP); Result = Connection.CallHTTPMethod("POST", HTTPRequest);

In this option, we will have to assemble the soap manually. Essentially, we simply wrap the xml from recipe 2 into a soap wrapper, where, depending on the requirements of the web service, we can change our soap as we please.

Next, we describe the headers according to the documentation. Some services will easily process our request even without headers; here we need to look at the specific case. If you don’t know what headers to write, then the easiest way is to look at the request in SoapUI by switching to the RAW tab.

The function for getting a Base64 string looks like this (I spied it):

Function GetBase64AuthorizationHeader(UserName, Password)FileEncoding = TextEncoding.UTF8; TemporaryFile = GetTemporaryFileName(); Entry = NewTextEntry(TemporaryFile, FileEncoding); Record.Record(UserName+":"+Password); Record.Close(); DvData = new BinaryData(TemporaryFile); Result = Base64String(DvData); DeleteFiles(TemporaryFile); Result = Avg(Result,5); Return Result; EndFunction

Eat important point. When working with an HTTP connection, specify the address without specifying the “http://” and “https://” protocols, otherwise you risk wasting time searching for an unobvious error.

Recipe 4. Send 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(StringSOAP); WinHttp.WaitForResponse(15); XMLResponse = WinHttp.ResponseText();

This is essentially the same as in the previous version, but we are working with a COM object. We indicate the connection string in full, along with the protocol. Special attention should be paid only to the flags for ignoring SSL certificate errors. They are needed if we work via 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 embedded inside the 1c HTTPRequest object.

On this moment These are all the recipes I have. If I come across new ones, I will definitely add to the article.

Processing the result

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

If Result.StatusCode = 200 Then ReadXML = New ReadXML; ReadXML.SetString(Result.GetBodyAsString()); ObjectResponse = OwnFactoryXDTO.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 intended for such work and will allow you to quickly understand how a particular service works. There is an article for mastering

2. If you are exchanging with a service over an unsecured http channel and the question arises about what exactly 1c is sending in its 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 install an Nginx server on a remote machine (any machine, most importantly not on our own), which we will contact, and it, in turn, will pack everything in https and forward it where needed ( 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 use of cookies, then the next one was found

P.S. If you have questions, suggestions for improving the code, have your own recipes that differ from those described, you found errors or think that the author is “incorrect” and “has no place in 1C”, then write comments and we will discuss everything.

  • Tutorial

Hi all!
It so happened that recently I began to develop web services. But today the topic is not about me, but about how we can write our own XML Web Service based on the SOAP 1.2 protocol.

I hope that after reading the topic you will be able to:

  • write your own server implementation of a web application;
  • write your own client implementation of a web application;
  • write your own web service description (WSDL);
  • send the client arrays of the same type of data to the server.
As you might have guessed, all the magic will happen with using PHP and the built-in SoapClient and SoapServer classes. Our rabbit will be a service for sending SMS messages.

1 Problem statement

1.1 Boundaries

At the beginning, I propose to deal with the result that we will achieve at the end of the topic. As announced above, we will write a service for sending SMS messages, and more precisely, we will receive messages from different sources via the SOAP protocol. After which, we will consider in what form they come to the server. The process of queuing messages for further sending to the provider, unfortunately, is beyond the scope of this post for many reasons.

1.2 What data will we change?

Great, we have decided on the boundaries! Next step What needs to be done is to decide what data we will exchange between the server and the client. On this topic, I suggest not to split hairs for too long and immediately answer the main questions for yourself:
  • What minimum data must be sent to the server in order to send an SMS message to a subscriber?
  • What minimum data must be sent from the server to satisfy the client's needs?
Something tells me that for this you need to send the following: In principle, these two characteristics are enough for sending, but I immediately imagine the case of an SMS with birthday greetings coming to you at 3 o’clock in the morning, or 4! At this moment, I will be very grateful to everyone for not forgetting about me! Therefore, we will also send to the server and
  • date of sending the SMS message.
The next thing I would like to send to the server is:
  • Message type.
This parameter is not mandatory, but it can be very useful to us if we quickly need to tell the boss how many of our clients we have “delighted” with our news, and also draw some beautiful statistics on this matter.

And yet, I forgot something! If we reflect a little more, it is worth noting that the client can send either one SMS message or a number of them to the server at a time. In other words, one data packet can contain from one to infinity messages.

As a result, we get that to send an SMS message we need the following data:

  • Mobile phone number,
  • SMS message text,
  • time of sending the SMS message to the subscriber,
  • message type.

We have answered the first question, now we need to answer the second question. And perhaps I’ll allow myself to mess around a little. Therefore, from the server we will send only Boolean data, the meaning of which has the following meaning:

  • TRUE – the packet successfully reached the server, passed authentication and queued for sending to the SMS provider
  • FALSE – in all other cases

This concludes the description of the problem statement! And finally, let's get down to the fun part - let's figure out what kind of strange beast this SOAP is!

2 What is SOAP?

In general, initially I did not plan to write anything about what SOAP is and wanted to limit myself to links to the w3.org website with the necessary specifications, as well as links to Wikipedia. But at the very end I decided to write a short note about this protocol.

And I will begin my story with the fact that this data exchange protocol belongs to a subset of protocols based on the so-called RPC (Remote Procedure Call) paradigm, the antipode of which is REST (Representational State Transfer). You can read more about this on Wikipedia; links to articles are at the very end of the topic. From these articles we need to understand the following: “The RPC approach allows the use of a small number of network resources with a large number of methods and a complex protocol. With the REST approach, the number of methods and protocol complexity are strictly limited, which means the number of individual resources can be large.” That is, in relation to us, this means that in the case of the RPC approach on the site there will always be one input (link) to the service and what procedure to call to process incoming data we transfer along with the data, while with the REST approach in our The site has many inputs (links), each of which accepts and processes only certain data. If anyone reading knows how to explain the difference in these approaches even more simply, be sure to write in the comments!

The next thing we need to know about SOAP is that this protocol uses the same XML as a transport, which on the one hand is very good, because immediately our arsenal receives the full power of a stack of technologies based on given language markup, namely XML-Schema - a language for describing the structure of an XML document (thanks Wikipedia!), which allows automatic validation of data received by the server from clients.

And so, now we know that SOAP is a protocol used to implement remote procedure calls and it uses XML as a transport! If you read the article on Wikipedia, you can also learn from there that it can be used over any application-level protocol, and not just in combination with HTTP (unfortunately, in this topic we will only consider SOAP over HTTP). And you know what I like most about all this? If there are no guesses, then I’ll give a hint - SOAP!... Still no guesses?... Are you sure you read the article on Wikipedia?... In general, I won’t torture you further. Therefore, I’ll go straight to the answer: “SOAP (from the English Simple Object Access Protocol - simple protocol access to objects; up to specification 1.2)". The most remarkable thing about this line is in italics! I don’t know what conclusions you drew from all this, but I see the following - since this protocol cannot in any way be called “simple” (and apparently even w3 agrees with this), then from version 1.2 it stopped being decrypted somehow! And it became known as SOAP, just SOAP, period.

Well, okay, please excuse me, I got a little sidetracked. As I wrote earlier, XML is used as transport, and the packets that travel between the client and server are called SOAP envelopes. If you consider the general structure of the envelope, it will seem very familiar to you, because... resembles the structure of an HTML page. It has a main section - Envelop, which includes sections Header And Body, or Fault. IN Body data is transmitted and it is a mandatory section of the envelope, while Header is optional. IN Header authorization or any other data that is not directly related to the input data of the web service procedures may be transmitted. About Fault there is nothing special to tell, except that it comes to the client from the server in case of any errors.

This is where my review story about the SOAP protocol ends (we will look at the envelopes themselves and their structure in more detail when our client and server finally learn to run them at each other) and a new one begins - about the SOAP companion called WSDL(Web Services Description Language). Yes, yes, this is the very thing that scares away most of us from even trying to take and implement our API on this protocol. As a result, we usually reinvent our wheel with JSON as transport. So what is WSDL? WSDL is a language for describing web services and accessing them, based on the XML language (c) Wikipedia. If this definition does not make clear to you the entire sacred meaning of this technology, then I will try to describe it in my own words!

WSDL is designed to allow our clients to communicate normally with the server. To do this, the file with the extension “*.wsdl” describes the following information:

  • What namespaces were used?
  • What data schemas were used?
  • What types of messages does the web service expect from clients?
  • Which data belongs to which web service procedures,
  • What procedures does the web service contain?
  • How should the client call the web service procedures,
  • To which address should customer calls be sent?
As seen, this file and there is the entire web service. By specifying the address of the WSDL file in the client, we will know everything about any web service! As a result, we do not need to know absolutely nothing about where the web service itself is located. All you need to know is the location of its WSDL file! We will soon find out that SOAP is not as scary as Russian proverbs make it out to be.

3 Introduction to XML-Schema

Now we know a lot about what SOAP is, what is inside it, and have an overview of the technology stack that surrounds it. Since, first of all, SOAP is a way of interaction between a client and a server, and XML markup language is used as a transport for it, then in this section We’ll take a little look at how automatic data validation occurs using XML schemas.

The main task of the diagram is to describe the structure of the data that we are going to process. All data in XML schemas is divided into simple(scalar) and complex(structures) types. Simple types include the following types:

  • line,
  • number,
  • boolean value,
  • date of.
Something very simple that has no extensions inside. Their antipode is complex complex types. The simplest example of a complex type that comes to everyone’s mind is objects. For example, a book. The book consists of properties: author, Name, price, ISBN number etc. And these properties, in turn, can be either simple types or complex ones. And the task of the XML schema is to describe this.

I suggest not going far and writing an XML schema for our SMS message! Below is the xml description of the SMS message:

71239876543 Test message 2013-07-20T12:00:00 12
Our complex type diagram will look like this:


This entry reads as follows: We have a variable " message" type " Message" and there is a complex type called " Message", which consists of a sequential set of elements " phone" type string, « text" type string, « date" type dateTime, « type" type decimal. These types are simple and are already defined in the schema description. Congratulations! We just wrote our first XML Schema!

I think that the meaning of the elements " element" And " complexType"Everything has become more or less clear to you, so we won’t focus on them any more and let’s switch straight to the composer element" sequence" When we use the composer element " sequence“We inform you that the elements included in it must always be located in the sequence specified in the diagram, and all of them are mandatory. But don't despair! There are two more composer elements in XML schemas: " choice" And " all" Composer " choice" announces that there must be one of the elements listed in it, and the composer " all» – any combination of the listed elements.

As you remember, in the first section of the topic we agreed that from one to infinity SMS messages can be transmitted in a package. Therefore, I propose to understand how such data is declared in the XML schema. The general package structure might look like this:

71239876543 Test message 1 2013-07-20T12:00:00 12 71239876543 Test message N 2013-07-20T12:00:00 12
The diagram for such a complex type will look like this:


The first block contains the familiar declaration of the complex type “ Message" If you noticed, then in each simple type included in " Message", new clarifying attributes have been added " minOccurs" And " maxOccurs" As you might guess from the name, the first ( minOccurs) indicates that this sequence must contain at least one element of type " phone», « text», « date" And " type", while the next one ( maxOccurs) attribute declares to us that there is at most one such element in our sequence. As a result, when we write our own schemas for any data, we are given the widest choice in how to configure them!

The second block of the diagram declares the element " messageList" type " MessageList" It's clear that " MessageList" is a complex type that contains at least one element " message", But maximum number There is no limit to such elements!

4 Write your WSDL

Do you remember that WSDL is our web service? I hope you remember! As we write it, our little web service will run on it. Therefore, I suggest not to mess around.

In general, in order for everything to work correctly for us, we need to transfer a WSDL file with the correct MIME type to the client. To do this, you need to configure your web server accordingly, namely, set the MIME type for files with the “*.wsdl” extension to the following line:

Application/wsdl+xml
But in practice, I usually sent the HTTP header via PHP " text/xml»:

Header("Content-Type: text/xml; charset=utf-8");
and everything worked great!

I want to warn you right away that our simple web service will have a rather impressive description, so don’t be alarmed, because... Most of the text is obligatory water and, having written it once, you can constantly copy it from one web service to another!

Since WSDL is XML, you need to write about this directly in the very first line. The root element of the file should always be called " definitions»:


Typically, WSDL consists of 4-5 main blocks. The very first block is the definition of a web service or, in other words, the entry point.


It says here that we have a service called - “ SmsService" In principle, all the names in the WSDL file can be changed by you to whatever you want, because they play absolutely no role.

After this we announce that in our web service " SmsService" there is an entry point ("port") called " SmsServicePort" It is to this entry point that all requests from clients to the server will be sent. And indicate in the element “ address» link to the handler file that will accept requests.

Once we have defined the web service and specified the entry point for it, we need to bind supported procedures to it:


To do this, it lists which operations and in what form they will be called. Those. for port " SmsServicePort" a binding is defined under the name " SmsServiceBinding", which has a call type " rpc"and HTTP is used as the transmission protocol. Thus, we indicated here that we will make an RPC call over HTTP. After this we describe which procedures ( operation) are supported in the web service. We will support only one procedure – “ sendSms" Through this procedure our wonderful messages will be sent to the server! After the procedure has been declared, it is necessary to indicate in what form the data will be transmitted. In this case, it is indicated that standard SOAP envelopes will be used.

After that, we need to bind the procedure to messages:


To do this, we specify that our binding is of type " SmsServicePortType" and in the element " portType"with the name of the same type, we indicate the binding of procedures to messages. So, incoming message(from client to server) will be called " sendSmsRequest", and outgoing (from server to client) " sendSmsResponse" Like all names in WSDL, the names of incoming and outgoing messages are arbitrary.

Now we need to describe the messages themselves, i.e. incoming and outgoing:


To do this we add the elements " message" with names " sendSmsRequest" And " sendSmsResponse" respectively. In them we indicate that the input should be an envelope whose structure corresponds to the data type " Request" After which an envelope is returned from the server containing the data type - “ Response».

Now we need to do just a little - add a description of these types to our WSDL file! And how do you think the WSDL describes incoming and outgoing data? I think that you have already understood everything a long time ago and told yourself that using XML schemas! And you will be absolutely right!


You can congratulate us! Our first WSDL has been written! And we are one step closer to achieving our goal.
Next, we'll look at what PHP provides us with for developing our own distributed applications.

5 Our first SOAP server

Earlier I wrote that to create a SOAP server in PHP we will use the built-in SoapServer class. In order for all further actions to happen the same way as for me, you will need to tweak your PHP a little. To be even more precise, you need to make sure that you have the “php-soap” extension installed. It is best to read how to install it on your web server on the official PHP website (see the list of references).

After everything has been installed and configured, we will need to create a file in the root folder of your hosting “ smsservice.php» with the following content:

setClass("SoapSmsGateWay"); //Start the server $server->handle();
I hope there is no need to explain what is above the line with the “ini_set” function. Because there it is determined which HTTP headers we will send from the server to the client and the environment is configured. In the line with “ini_set” we disable caching of the WSDL file so that our changes in it immediately take effect on the client.

Now we come to the server! As you can see, the entire SOAP server takes only three lines! On the first line, we create a new instance of the SoapServer object and pass the address of our WSDL description of the web service to its constructor. Now we know that it will be located in the root of the hosting in a file with the self-explanatory name “ smsservice.wsdl.php" In the second line, we tell the SOAP server which class needs to be pulled in order to process the envelope received from the client and return the envelope with the response. As you might have guessed, it is in this class that our only method will be described sendSms. On the third line we start the server! That's it, our server is ready! With which I congratulate us all!

Now we need to create the WSDL file. To do this, you can either simply copy its contents from the previous section, or take liberties and “template” it a little:

"; ?> /" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:http="http:// schemas.xmlsoap.org/wsdl/http/" name="SmsWsdl" xmlns="http://schemas.xmlsoap.org/wsdl/"> /"> /smsservice.php" />
At this stage, we should be completely satisfied with the resulting server, because We can log the envelopes coming to it and then calmly analyze the incoming data. In order for us to receive anything on the server, we need a client. So let's get to it!

6 SOAP client on the way

First of all, we need to create a file in which we will write the client. As usual, we will create it in the root of the host and call it " client.php", and inside we will write the following:

messageList = new MessageList(); $req->messageList->message = new Message(); $req->messageList->message->phone = "79871234567"; $req->messageList->message->text = "Test message 1"; $req->messageList->message->date = "2013-07-21T15:00:00.26"; $req->messageList->message->type = 15; $client = new SoapClient("http://($_SERVER["HTTP_HOST"])/smsservice.wsdl.php", array("soap_version" => SOAP_1_2)); var_dump($client->sendSms($req));
Let's describe our objects. When we wrote the WSDL, it described three entities for the envelope incoming to the server: Request, MessageList And Message. Accordingly classes Request, MessageList And Message are reflections of these entities in our PHP script.

Once we have defined the objects, we need to create an object ( $req), which we will send to the server. After which come the two most cherished lines for us! Our SOAP client! Believe it or not, this is enough for our server to start receiving messages from the client, as well as for our server to successfully receive and process them! In the first of them, we create an instance of the SoapClient class and pass the address of the location of the WSDL file to its constructor, and in the parameters we explicitly indicate that we will work using the SOAP protocol version 1.2. On the next line we call the method sendSms object $client and immediately display the result in the browser.
Let's run it and see what we finally got!

The following object was returned to me from the server:

Object(stdClass) public "status" => boolean true
And this is great, because... Now we know for sure that our server is working and not only works, but can also return some values ​​to the client!

Now let's look at the log that we prudently keep on the server side! In its first part we see the raw data that arrived on the server:

79871234567 Test message 1 2013-07-21T15:00:00.26 15
This is the envelope. Now you know what it looks like! But it’s unlikely that we’ll be interested in looking at it all the time, so let’s deserialize the object from the log file and see if everything is fine:

Object(stdClass) public "messageList" => object(stdClass) public "message" => object(stdClass) public "phone" => string "79871234567" (length=11) public "text" => string "Test message 1 " (length=37) public "date" => string "2013-07-21T15:00:00.26" (length=22) public "type" => string "15" (length=2)
As you can see, the object was deserialized correctly, for which I want to congratulate us all! Something more interesting awaits us next! Namely, we will send the client to the server not just one SMS message, but a whole pack (to be more precise, three)!

7 Sending complex objects

Let's think about how we can transfer a whole bunch of messages to the server in one packet? Probably the most in a simple way there will be an array organization inside the messageList element! Let's do this:

// create an object to send to the server $req = new Request(); $req->messageList = new MessageList(); $msg1 = new Message(); $msg1->phone = "79871234567"; $msg1->text = "Test message 1"; $msg1->date = "2013-07-21T15:00:00.26"; $msg1->type = 15; $msg2 = new Message(); $msg2->phone = "79871234567"; $msg2->text = "Test message 2"; $msg2->date = "2014-08-22T16:01:10"; $msg2->type = 16; $msg3 = new Message(); $msg3->phone = "79871234567"; $msg3->text = "Test message 3"; $msg3->date = "2014-08-22T16:01:10"; $msg3->type = 17; $req->messageList->message = $msg1; $req->messageList->message = $msg2; $req->messageList->message = $msg3;
Our logs indicate that the following packet was received from the client:

79871234567 Test message 1 2013-07-21T15:00:00.26 15 79871234567 Test message 2 2014-08-22T16:01:10 16 79871234567 Test message 3 2014-08-22T16:01:10 17
What nonsense, you say? And you will be right in a sense, because... As soon as we learned that an object left the client, it came to our server in absolutely the same form in the form of an envelope. True, SMS messages were not serialized in XML in the way we needed - they had to be wrapped in elements message, not in Struct. Now let's see in what form such an object comes to the method sendSms:

Object(stdClass) public "messageList" => object(stdClass) public "message" => object(stdClass) public "Struct" => array (size=3) 0 => object(stdClass) public "phone" => string "79871234567" (length=11) public "text" => string "Test message 1" (length=37) public "date" => string "2013-07-21T15:00:00.26" (length=22) public " type" => string "15" (length=2) 1 => object(stdClass) public "phone" => string "79871234567" (length=11) public "text" => string "Test message 2" (length= 37) public "date" => string "2014-08-22T16:01:10" (length=19) public "type" => string "16" (length=2) 2 => object(stdClass) public "phone " => string "79871234567" (length=11) public "text" => string "Test message 3" (length=37) public "date" => string "2014-08-22T16:01:10" (length= 19) public "type" => string "17" (length=2)
What does this knowledge give us? Only that the path we have chosen is not correct and we have not received an answer to the question - “How can we get on the server correct structure data? But I suggest not to despair and try to convert our array to the type an object:

$req->messageList->message = (object)$req->messageList->message;
In this case, we will receive another envelope:

79871234567 Test message 1 2013-07-21T15:00:00.26 15 79871234567 Test message 2 2014-08-22T16:01:10 16 79871234567 Test message 3 2014-08-22T16:01:10 17
Came into the method sendSms the object has the following structure:

Object(stdClass) public "messageList" => object(stdClass) public "message" => object(stdClass) public "BOGUS" => array (size=3) 0 => object(stdClass) public "phone" => string "79871234567" (length=11) public "text" => string "Test message 1" (length=37) public "date" => string "2013-07-21T15:00:00.26" (length=22) public " type" => string "15" (length=2) 1 => object(stdClass) public "phone" => string "79871234567" (length=11) public "text" => string "Test message 2" (length= 37) public "date" => string "2014-08-22T16:01:10" (length=19) public "type" => string "16" (length=2) 2 => object(stdClass) public "phone " => string "79871234567" (length=11) public "text" => string "Test message 3" (length=37) public "date" => string "2014-08-22T16:01:10" (length= 19) public "type" => string "17" (length=2)
As for me, “the sum does not change from changing the places of the terms” (c). What BOGUS, What Struct– we have not yet achieved our goal! And to achieve it, we need to make sure that instead of these incomprehensible names our native one is displayed message. But the author does not yet know how to achieve this. Therefore, the only thing we can do is get rid of the extra container. In other words, we will now make sure that instead of message became BOGUS! To do this, change the object as follows:

// create an object to send to the server $req = new Request(); $msg1 = new Message(); $msg1->phone = "79871234567"; $msg1->text = "Test message 1"; $msg1->date = "2013-07-21T15:00:00.26"; $msg1->type = 15; $msg2 = new Message(); $msg2->phone = "79871234567"; $msg2->text = "Test message 2"; $msg2->date = "2014-08-22T16:01:10"; $msg2->type = 16; $msg3 = new Message(); $msg3->phone = "79871234567"; $msg3->text = "Test message 3"; $msg3->date = "2014-08-22T16:01:10"; $msg3->type = 17; $req->messageList = $msg1; $req->messageList = $msg2; $req->messageList = $msg3; $req->messageList = (object)$req->messageList;
What if we get lucky and the correct name comes up from the diagram? To do this, let's look at the envelope that arrived:

79871234567 Test message 1 2013-07-21T15:00:00.26 15 79871234567 Test message 2 2014-08-22T16:01:10 16 79871234567 Test message 3 2014-08-22T16:01:10 17
Yes, a miracle did not happen! BOGUS– we won’t win! Came to sendSms the object in this case will look like this:

Object(stdClass) public "messageList" => object(stdClass) public "BOGUS" => array (size=3) 0 => object(stdClass) public "phone" => string "79871234567" (length=11) public " text" => string "Test message 1" (length=37) public "date" => string "2013-07-21T15:00:00.26" (length=22) public "type" => string "15" (length =2) 1 => object(stdClass) public "phone" => string "79871234567" (length=11) public "text" => string "Test message 2" (length=37) public "date" => string " 2014-08-22T16:01:10" (length=19) public "type" => string "16" (length=2) 2 => object(stdClass) public "phone" => string "79871234567" (length= 11) public "text" => string "Test message 3" (length=37) public "date" => string "2014-08-22T16:01:10" (length=19) public "type" => string " 17" (length=2)
As they say – “Almost”! On this (slightly sad) note, I propose to slowly wrap things up and draw some conclusions for ourselves.

8 Conclusion

Finally we got here! Let's figure out what you can do now:
  • you can write the WSDL file necessary for your web service;
  • you can easily write your own client that can communicate with the server via SOAP;
  • you can write your own server that communicates with the outside world via SOAP;
  • you can send arrays of the same type of objects to the server from your client (with some restrictions).
We also made some discoveries during our little research:
  • the native SoapClient class does not correctly serialize data structures of the same type in XML;
  • when serializing an array to XML it creates an extra element called Struct;
  • when serializing an object to XML it creates an extra element called BOGUS;
  • BOGUS less evil than Struct due to the fact that the envelope is more compact (extra namespaces are not added to the XML header of the envelope);
  • Unfortunately, the SoapServer class does not automatically validate the envelope data with our XML schema (perhaps other servers do not do this either).

Alexey Boyko

SOAP and XML web services on the .Net platform

XML Web services offer a level of compatibility and interoperability across operating systems that

platforms and languages ​​that were previously simply unavailable.

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

If you haven't worked with XML web services before, you've probably heard the word "SOAP". It's time to understand these concepts.

Intro

If you're interested in the Internet or smaller networks, you'll likely come across XML web services sooner or later. An XML web service is not just a web application that can output information to a browser. Rather, it is a remoting technology that allows you to call methods and properties of an object on the network using standard HTTP requests.

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

HTTP methods GET or POST can be used as information “transport” between the service and the client.

Or you can “overlay” another protocol on top - SOAP (Simple Object Access Protocol). This is usually done, since in this case it is possible to pass complex types (including user ones). But the classic GET and POST methods only support lists, simple arrays and strings.

SOAP Interop Example

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

Listing 1. SOAP message structure

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

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

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

Listing 2. Example SOAP request

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

Listing 3. Example 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 on the .NET 2.0 Platform

You can create a service different ways, we will use Visual Studio 2005. Click “File -> New -> Web Site”, in the window that opens, 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 defined 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 program code that implements the HelloWorld() method:

Listing 5. Service.cs file implementing the 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";

This is of no use to us, and we will not do this.

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

Such a simple service is quite suitable for our experiments; all that remains is to publish it.

Publishing an 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.

First of all, install IIS (Internet Information Server). To do this, open the “Add or Remove Programs” window and select “Install Windows components" (Some Windows versions don't assume installing IIS, for example Windows XP Home Edition.)

Note: It is better to install the IIS server before 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 Virtual Directory Creation Wizard will launch. Specify Soap1 as the alias and set 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.

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

Viewing SOAP Messages

The testing page does not allow you to send or read SOAP messages. For this reason, you will have to use third-party developments; 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 automatically by soapUI.)

What is this WSDL? A WSDL document describes how clients can interact with a web service. It describes which service methods are available for external call, what parameters they accept and what they return, as well as other information necessary for remote interaction. Such a document can be created manually, or you can entrust its generation to the server; to do this, just add the ?wsdl suffix to the URL pointing to the *.asmx file.

To view the WSDL document of our service, enter http://localhost/soap1/Service.asmx?wsdl in your browser. SoapUI uses the information from this document to automatically generate SOAP requests.

SOAP Extensions

As you've probably noticed, to create an XML web service (as well as a client), you don't necessarily need to care about the type of SOAP messages. It is enough to mark the necessary methods with the attribute, and the ASP.NET runtime itself will compose packages of the required format.

In Fig. Figure 4 shows the web service request and response received using the soapUI program.

Let's repeat it again. The request is generated by soapUI - when creating real clients for the service, you also do not need to manually format SOAP packets. We also did not directly participate in creating 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 customize the received and sent SOAP messages.

"Path" of a SOAP message

To begin 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 that describes an object being transmitted over a network. Before using the object passed in this way, it must be restored (or, if you prefer, assembled) from this description. An XML serializer serves this purpose.

Incoming packets undergo deserialization (recovery of an object from an XML description), and sent packets undergo serialization (creation of an XML description of an object).

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

Implementing SOAP Extension

First, let's define the task: let's say we want to change 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">

Ciphertext

Action plan for implementing SOAP Extension:

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

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

Creating a 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 SOAP package modifications we need. This class must inherit from the SoapExtension class.

Listing 8. Creating a class that inherits 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 being transferred over the network (before or after serialization). And it must return the stream.

A 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 “insets” (see Fig. 6).

To obtain these streams, the ChainStream method is used.

Listing 9. Implementation of the ChainStream method

public class TraceExtension: SoapExtension

Stream wireStream;

Stream appStream;

// method as input parameter

// receives a stream containing the passed object

Public override Stream ChainStream(Stream stream)

WireStream = stream;

AppStream = new MemoryStream();

Return appStream;

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

And at the AfterSerialize point, you need to pass the SOAP response sent to the network to the wireStream stream, which will be located in 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 performing mandatory copying

// threads at two points (BeforeDeserialize and AfterSerialize)

Switch (message.Stage)

// at the BeforeDeserialize point you must pass

// SOAP request from a network stream (wireStream)

// to the application stream (appStream)

Case SoapMessageStage.BeforeDeserialize:

Copy(wireStream, appStream);

AppStream.Position = 0;

Break;

// at the AfterSerialize point you need to pass

// SOAP response from application thread to network thread

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();

Listing 10 can be taken as a blank for further experiments. This implementation of the ProcessMessage method makes no sense - the outgoing SOAP response is not modified in any way. Let's fix this:

Listing 11. Implementation of the ProcessMessage method that modifies a SOAP response

public override void ProcessMessage(SoapMessage message)

Switch (message.Stage)

Case SoapMessageStage.AfterSerialize:

WriteOutput(message);

Break;

// part of the code has been 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";

// clear the stream and write a new SOAP response to it

AppStream.SetLength(0);

AppStream.Position = 0;

Document.Save(appStream);

// REQUIRED ACTION

// send a SOAP response from the application stream (appStream)

// to the network stream (wireStream)

AppStream.Position = 0;

Copy(appStream, wireStream);

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

Listing 12. Other mandatory methods

// According to 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, let's compile the project. Finally we got a dll with SOAP Extension. The full listing of SoapExtensionLib.dll is on the magazine's website in the "Source Code" section.

Configuring a web service to work with SOAP Extension

Again, open our XML Web Service project using 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 application automatically links to *.dll files located in the Bin folder.

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

Listing 13. Web.Config file

Priority="1"

Group="0" />

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

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

Listing 14. The webServices section in the Web.Config file

Priority="1"

Group="0" />

As you already know, you can make multiple SOAP Extensions, and the stream carrying the passed object (before or after serialization) will pass through each of them. The order in which a flow traverses different 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 service method 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. Example of using a custom attribute

public string HelloWorld() (

Return "Hello World";

To do this, you need to 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 sufficient so that, if necessary, you can engage in a more in-depth study of the topic.


In contact with

In general, today there are standard XML data exchange protocols:

  • XML-RPC– you pass the package and indicate which method on the server you want to call.
  • REST- there are some objects on the server. Each object is characterized by some kind of identifier. Each element has its own url. You can do the following with any element: insert, delete, update, select. You simply send the desired request to the server (for example, insert such and such an element). Client-server exchange is based on either JSON or XML.

SOAP (service oriented architecture, a set of loosely coupled services interacting with each other) is based on RPC. The main advantage of RPC is the small number of network resources (entry points) and the many methods involved. Despite this advantage, RPC is an outdated protocol that has a number of disadvantages:

  • The validity of an XML-RPC message cannot be verified. The old protocol was created before schemas (methods of validating data) were standardized in XML. Those. The server accepts requests, it must ensure that the requests are for it and that the data is consistent. In XML-RPC, data types are declared for this, but this is a data type check, and data consistency is not checked (that you received a structure with all the necessary parameters).
  • You cannot create combined messages.
  • You cannot use space and time (appeared after the creation of RPC).
  • You cannot expand the message, i.e. add additional information.

All these shortcomings were solved in XML Schema. This is the industry standard for describing an XML document. Those. it is a way to model arbitrary data. An XML schema can describe a model (relationships between elements and attributes, and their structure), data types (characterizes data types) and a dictionary (names of elements and attributes).

Based on all the shortcomings of XML-RPC, the SOAP protocol was created.

SOAP(Simle Object Access Protocol) - access protocol to an object (to the entry point). Today it is the main industry standard for building distributed applications.

It represents extensions to the XML-RPC language. Those. it is built on the principle: 1 entry point and any methods. The protocol itself in terms of transport (how to transfer data) gives a wide choice: SMTP, FTP, HTTP, MSMQ.

SOAP underlies the implementation of XML web services (XML web services). The disadvantage of SOAP is that it is difficult to learn.

SOAP is based on the exchange of messages between a client and a server (synchronously and asynchronously). Each message carries information about the data (what data is transmitted and received). SOAP describes in advance the entire structure of a message using XML schemas: what should be in the message, how it will be transmitted. This makes it possible, without knowing the server, to understand what is happening there, and allows the server to check whether this message is for it.

XML schema

The purpose of a schema is to describe the structure of the data, i.e. what we have. All data is divided into simple and complex types (scalars and structures). A simple type (string, number, boolean, date) will never contain anything inside. And a structure (object) can contain properties.

Basic SOAP Operations

  • Not just simple client-server information exchange. But also automatic server recognition and search for this server, i.e. the client may not even know anything about the server. Those. the client first searches for the server, finds suitable services, understands what methods are there, what the server has, and calls it.
  • The server publishes its information (location, what methods it supports) so that the client finds this server. Publishing occurs in the UDDI directory.

SOAP message structure:

  • SOAP Envelope - this includes the entire message. Consists of a header and a body.
  • SOAP Header (header) - additional information (authorization, for example).
  • SOAP Body (body) - the message itself.
  • SOAP Fault (error) is a method of transmitting an error from the server to the client.

WSDL

WSDL(Web Services Description Language) - language for describing web services. Used in SOAP. This is a kind of document that describes everything: what namespaces were used, what data schemes were used, what types of messages the server expects from the client, what envelopes belong to what method, what methods exist, what address to send to, etc. Actually, WSDL is a web service. It is enough for the client to study the contents of this document; he already knows everything about the server.

Any server must publish WSDL.

WSDL consists of blocks:

  • Definition of the service itself, i.e. entry point, port is indicated.
  • Methods format. The entry point is linked to operations, i.e. what methods does it support? The type of call and transmission method are indicated. Inside each method there is an explanation of the form in which the data is transmitted - in the form of SOAP.
  • Binding methods to a message.
  • Description of the messages themselves.

Lyrical part.

Imagine that you have implemented or are implementing 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, do some calculations, etc. live and possibly develop according to the scenario known to him (i.e. according to the developers’ scenario). It is not interesting for a person to communicate with such a server, because he may not be able/want to provide beautiful pages with pictures and other user-friendly content. It is written and works to work and provide data when asked to it, without worrying that it is human readable, the client will deal with it himself.

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

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

Practical part.

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

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

Not only simple types, but also objects and collections of objects can be passed as parameters. The description of an object comes down to a description of each component of the object. If an object consists of several fields, then each field is described, its type, name (what are the possible values). Fields can also be of a complex type, and so on until the description of the 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 ​​they may contain.

For clients, it is enough to know the url of the web service; the wsdl will always be nearby, from 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 automatically. Those. the programmer on the server just needs to say that this method can be called through a web service, and the wsdl description will be generated automatically.
  • The description, which has a clear structure, is readable by any soap client. Those. whatever the web service, the client will understand what data the web service receives. Using this description, the client can build its 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","admin"); soap.AddUser(NewUser);

  • Automatic validation.

    • xml validation. xml must be well-formed. Invalid xml - immediately an error to the client, let him sort it out.
    • schema-validation. xml must have a certain structure. xml does not match the schema - immediately an error to the client, let him sort it out.
    • Data verification is carried out by the soap server so that data types and restrictions match the description.
  • Authorization and authentication can be implemented using a separate method. natively. or using http authorization.
  • Web services can work both via the soap protocol and via http, that is, through get requests. That is, if the parameters are simple data (without 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 on Wikipedia

There are also a lot of disadvantages:

  • 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 redundancy. For intranet systems, the issue of traffic is less acute than for the internet, so soap for local networks is more in demand, in particular Sharepoint has a soap web service with which you can communicate with success (and some limitations).
  • Automatically changing the description of a web service can break all clients. Well, it’s like this for any system, if backward compatibility with old methods is not supported, everything will fall off...
  • Not a minus, but a drawback. All method calls must be atomic. For example, when working with a database, we can start a transaction, execute several queries, then rollback or commit. There are no transactions in soap. One request, one answer, the conversation is over.
  • Dealing with the description of what is on the server side (is everything described correctly?) and what is on the client (what was described to me here?) can be quite difficult. There were several times when I had to deal with the client side and convince the server programmer that his data was described incorrectly, but he couldn’t understand anything about it at all, because automatic generation and he shouldn’t, it’s a matter of software. And the error, naturally, was in the method code; the programmer simply did not see it.
  • Practice shows that web service developers are terribly far from the people who use these web services. In response to any request (valid from the outside), an incomprehensible error “Error 5. Everything is bad” may come. It all depends on the conscience of the developers :)
  • I'm sure I still don't remember something...

As an example, there is an 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 - description of a specific method with an example of the type of xml request and 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

PS Previously, the Aeroflot web service was opened, but after 1C added soap support to 8ku, a bunch of 1C beta testers successfully installed it. Now something has changed there (I don’t know the address, you can look it up if you’re interested).
ZZY Disclaimer. He spoke at the everyday level. You can kick.