Work with HTTP services in 1C. Part 2: POST method

Alexander Biryukov

22.04.2020 23 min

In the previous article, we made an HTTP service in 1C, to which you can connect from any application that works with REST API. This service can give away any data that is in 1C.

But now suppose we need to send data to the server. For this, a POST request is usually used. So now, let's complicate our example and add the implementation of the POST request to it.

Well, let's begin! We add the POST method for our HTTP Service:

 1

and also create the program code for this method:

2

For the test, add the text line output to the server's response:

 

Function ourAPIPOST(Request)

      Response = New HTTPServiceResponse(200);

      result = "This is POST method in 1C";

      Response.SetBodyFromString(result,TextEncoding.UTF8);

      Return Response;

EndFunction

Let's publish 1C on a web server and see how our POST request works. For debugging, I usually use the POSTMAN. Well, let's use it:

 

3

As you can see, our POST request works correctly.

For example, let's check how the GET request that we made earlier works:

4 

 

Everything works fine!

OK, complicate our example now.

Let's make another 1C application - better mobile - and this application will send data to the server using the POST request and receive data from the server back.

First, we will slightly modify our 1C server program. Add one attribute "Price" to the catalog "Products":

5

 

Attention! This is an example for a study. In fact, it's undesirable to store prices in catalogs. For this, it's better to use information registers.

Now create a new mobile 1C, add the catalog "Products" to it and also create one attribute "Price":

6

Let's also make the Common form "frmMain", and place two commands on it: "getProductsFromServer" and "postPriceToServer".

 

 7

The idea is this: the command "getProductsFromServer" will receive a list of products from the server (here we'll use the Get request, slightly modifying it). Then the user will set prices for the products, and then the command "postPriceToServer" will post all the data to the server. In the second command, we'll use the POST request.

So, for the command "getProductsFromServer" write the program code:

&AtClient

Procedure getProductsFromServer(Command)

      getProductsFromServerAtServer();

EndProcedure

&AtServer

Procedure getProductsFromServerAtServer()

      HTTPConnection = New HTTPConnection("localhost");

      HTTPRequest = New HTTPRequest("ourAPI/hs/ourAPI/V1/list");

      HTTPAnswer = HTTPConnection.Get(HTTPRequest);

      Result = HTTPAnswer.GetBodyAsString();

EndProcedure

 

For simplicity, I write the server address as a "localhost".

Let's run this code and see what result the server returns to us:

 

8

 

Everything works, the list of products from the server has come. Now it can be processed and recorded in the Products catalog, but it is not very convenient to work with such unstructured data.

Let's change the program code on the server so that the server returns a list of products in the form of a structure. Return to the server 1C and change the procedure "ourAPIGET" as follows:

 

Function ourAPIGET(Request)

      Response = New HTTPServiceResponse(200);

      MethodName = Request.URLParameters.Get("MethodName");

      If MethodName = "list" Then

            //result = GetProducts();

            structureResult = New Structure;

            structureResult.Insert("products", GetArrayProducts());

            JSONWriter = New JSONWriter;

            JSONWriter.SetString();

            WriteJSON(JSONWriter, structureResult);

            result = JSONWriter.Close();

      ElsIf MethodName = "product" Then

            Parameter = Request.QueryOptions.Get("code");

            If Parameter = Undefined Then

                  Response.StatusCode = 405;

                  result = "Parameter not defined";

            Else

                  result = GetProducts(Parameter);

            EndIf;

      Else

            Response.StatusCode = 405;

            result = "Not found Method: " + MethodName;

      EndIf;

      Response.SetBodyFromString(result,TextEncoding.UTF8);

      Response.Headers.Insert("Content-Type","text/html; charset=utf-8");

      Return Response;

EndFunction


Instead of the GetProducts function, the function GetArrayProducts is called. This function returns an array of data, which is then packed into the structure structureResult and then converted to the string JSON.

Below is the source code of the function GetArrayProducts:

 

Function GetArrayProducts()

      arrayProducts = New Array;

      query = New Query;

      query.Text = "SELECT

                   |    Products.Ref AS Ref,

                   |    Products.Code AS Code,

                   |    Products.Description AS Description,

                   |    Products.DeletionMark AS DeletionMark

                   |FROM

                   |    Catalog.Products AS Products";

      selection = query.Execute().Select();

      While selection.Next() Do

            structureProduct = New Structure("_GUID,_Code,_Description,_DeletionMark");

             structureProduct._GUID             = String(selection.Ref.UUID());

            structureProduct._Code             = selection.Code;

            structureProduct._Description      = selection.Description;

            structureProduct._DeletionMark     = selection.DeletionMark;

            arrayProducts.Add(structureProduct);

      EndDo;

      Return arrayProducts;

EndFunction


An array is created inside the function, then the elements are added to this array. Each element added is also a structure. And already the structure, in turn, stores information on each product.

Let's check how this code works. Request Postman:

 

9

 

This structured data can be processed in any programming language that can work with JSON.

We'll process this data in 1C, so we return to our mobile application and write the following code in the procedure getProductsFromServerAtServer:

&AtServer

Procedure getProductsFromServerAtServer()

      HTTPConnection = New HTTPConnection("localhost");

      HTTPRequest = New HTTPRequest("ourAPI/hs/ourAPI/V1/list");

      HTTPAnswer = HTTPConnection.Get(HTTPRequest);

      If Not HTTPAnswer.StatusCode = 200 Then

            Return;

      EndIf;

      result = HTTPAnswer.GetBodyAsString();

      JSONReader = New JSONReader;

      JSONReader.SetString(result);

      structureResult = ReadJSON(JSONReader);

      If TypeOf(structureResult) = Type("Structure") Then

            If structureResult.Property("products") Then

                  If TypeOf(structureResult.products) = Type("Array") Then

                        For Each curElement In structureResult.products Do

                              _guid = curElement._GUID;

                              refProduct = Catalogs.Products.GetRef(New UUID(_guid));

                              objectProduct = refProduct.GetObject();

                              If objectProduct = Undefined Then

                                   objectProduct = Catalogs.Products.CreateItem();

                                   objectProduct.SetNewObjectRef(refProduct);

                              EndIf;

                               objectProduct.Description    = curElement._Description;

                              objectProduct.Code            = curElement._Code;

                              objectProduct.DeletionMark    = curElement._DeletionMark;

                              objectProduct.Write();

                        EndDo;

                  EndIf;

            EndIf;

      EndIf;

EndProcedure

 

A little bit about how this code works.

First, GET request to the server is generated. Then, if the server returned StatusCode = 200, the request result is converted to JSON:


      result = HTTPAnswer.GetBodyAsString();

      JSONReader = New JSONReader;

      JSONReader.SetString(result);

      structureResult = ReadJSON(JSONReader);

  

After this, several checks will be performed that the result has the correct structure and the resulting array of products is processed in a cycle.

 

If TypeOf(structureResult) = Type("Structure") Then

            If structureResult.Property("products") Then

                  If TypeOf(structureResult.products) = Type("Array") Then

                        For Each curElement In structureResult.products Do

 

                        EndDo;

                  EndIf;

            EndIf;

      EndIf;

 

In addition to the product description, the server also returns GUID (UUID). According to this GUID, we are trying to find a product in our catalog "Products". If a product with such a GUID is in the catalog "Products", then its description and code are simply updated. If there is no such product, a new one is created, and the same GUID is installed for it.

_guid = curElement._GUID;

refProduct = Catalogs.Products.GetRef(New UUID(_guid));

objectProduct = refProduct.GetObject();

If objectProduct = Undefined Then

      objectProduct = Catalogs.Products.CreateItem();

      objectProduct.SetNewObjectRef(refProduct);

EndIf;

objectProduct.Description     = curElement._Description;

objectProduct.Code            = curElement._Code;

objectProduct.DeletionMark    = curElement._DeletionMark;

objectProduct.Write();

 

Let's check how this code works. Launch our 1C application, click the "getProductsFromServer" button, and then open the catalog "Products".

Well - all products from the server are in the catalog on our mobile device:

 

10

Excellent!

Now let's change the price of the products and transfer this data back to the server.

 

11

First create the code to process the PostPriceToServer command:

 

&AtClient

Procedure postPriceToServer(Command)

      postPriceToServerAtServer();

EndProcedure

 

&AtServer

Procedure postPriceToServerAtServer()

      structureResult = New Structure;

      structureResult.Insert("products", GetProducts());

      JSONWriter = New JSONWriter;

      JSONWriter.SetString();

      WriteJSON(JSONWriter, structureResult);

      result = JSONWriter.Close();

      HTTPConnection = New HTTPConnection("localhost");

      HTTPRequest = New HTTPRequest("ourAPI/hs/ourAPI/V1/post_products");

      HTTPRequest.SetBodyFromString(result);

      HTTPAnswer = HTTPConnection.Post(HTTPRequest);

      If Not HTTPAnswer.StatusCode = 200 Then

            Message("Data Transfer Error");

      EndIf;

EndProcedure

&AtServer

Function GetProducts()

      JSONWriter = New JSONWriter;

      arrayProducts = New Array;

      query = New Query;

      query.Text = "SELECT

                   |    Products.Ref AS Ref

                   |FROM

                   |    Catalog.Products AS Products";

      selection = query.Execute().Select();

      While selection.Next() Do

            JSONWriter.SetString();

            objectProduct = selection.Ref.GetObject();

            XDTOSerializer.WriteJSON(JSONWriter, objectProduct,XMLTypeAssignment.Explicit);

            stringProduct = JSONWriter.Close();

            arrayProducts.Add(stringProduct);

      EndDo;

      Return arrayProducts;

EndFunction

 

The principle of operation is similar to the "ourAPIGET" procedure on the server. The structure "structureResult" is formed, an array of "products" is added to this structure.

But in the array itself, data on products are formed differently. If in the procedure "ourAPIGET" we saved each product attribute separately (for this, we used another structure "structureProduct"), now we record all the product attributes with one command. For this, the 1C object "XDTOSerializer" is used:

 

JSONWriter.SetString();

XDTOSerializer.WriteJSON(JSONWriter, objectProduct, XMLTypeAssignment.Explicit);

stringProduct = JSONWriter.Close();

 

Using the "XDTOSerializer" object allows us to simplify both the source code and the subsequent support of the program.

Suppose we later needed to add additional attributes to the catalog "Products". If you use the first version of the source code (without using the object "XDTOSerializer"), then you will have to change the source code of our procedures both on the server and on the clients.

If you use the "XDTOSerializer" object, you won't have to change the code, since in this case, all newly added attributes will automatically be processed.

Well, let's create program code on the server to process the POST request:

Function ourAPIPOST(Request)

      Response = New HTTPServiceResponse(200);

      result = "OK";

      MethodName = Request.URLParameters.Get("MethodName");

      If MethodName = "post_products" Then

            stringResult = Request.GetBodyAsString("UTF-8");

            JSONReader = New JSONReader;

            JSONReader.SetString(stringResult);

            structureResult = ReadJSON(JSONReader);

            JSONReader.Close();

            If TypeOf(structureResult) = Type("Structure") Then

                   If structureResult.Property("products") Then

                         If TypeOf(structureResult.products) = Type("Array") Then

                               For Each curElement In structureResult.products Do

                                   JSONReader.SetString(curElement);

                                   objectProduct = XDTOSerializer.ReadJSON(JSONReader);

                                   Try

                                         objectProduct.Write();

                                   Except

                                         result = "Error writing object";

                                         Response.StatusCode = 400;

                                         Break;

                                   EndTry;

                                   JSONReader.Close();

                               EndDo;

                        EndIf;

                   EndIf;

            EndIf;

      Else

            Response.StatusCode = 405;

            result = "Not found Method: " + MethodName;

      EndIf;

      Response.SetBodyFromString(result,TextEncoding.UTF8);

      Return Response;

EndFunction

 

To convert product data into 1C object, "XDTOSerializer" is also used here:

objectProduct = XDTOSerializer.ReadJSON(JSONReader);

 Well, now we can check how our program works. Open the mobile application, change product prices there, then click the "postPriceToServer" button. After that, open the server application and look at the catalog "Products" there:

 12

All the prices from the mobile application hit the server. We have completed the task!

Thus, using HTTP services, you can create any exchanges data between your 1C program and any other software products.

You can download this Example for your own application.

If you have any questions about this article, you can always ask them on our forum: https://1c-dn.com/forum/

 

Stay with us!

Be the first to know tips & tricks on business application development!

A confirmation e-mail has been sent to the e-mail address you provided .

Click the link in the e-mail to confirm and activate the subscription.