RESTRequest.Execute error - No mapping for the Unicode character exists in the target multi-byte code page

3.3k views Asked by At

I'm using Delphi 10.4 (with patches 1, 2 and 3) on Windows 10 64bit to build a VCL Web Client application.

I have an API running on RAD Server, and I can get information from it using the below VCL Webclient application with no trouble. However, when I try to insert data into the API resources through a POST method, I got the following error message from the TRESRequest.Execute() method call:

No mapping for the Unicode character exists in the target multi-byte code page

Though I got this error message, the JSON data is being sent to the API and is saved to the database correctly. It seems that at a certain point of the Execute() method, an error is generated after the data has been sent to the server.

I've already tried TEncoding.UTF8.GetBytes(), TEncoding.ASCII.GetBytes(), and Unicode, without success.

This is my code:

procedure TForm1.BTPostClick(Sender: TObject);
var
  strjson : string;
  jo      : TJSONObject;
begin
  strjson :=
    '{'                                 +
      '"CUST_ID": 1500,'                +
      '"CUST_NAME": "John Doe Max",'    +
      '"CUST_COUNTERTOTAL": "500",'     +
      '"CUST_DETAILS": "This is just a test"' +
    '}';    

  //    jo := TJSONObject.ParseJSONValue(TEncoding.Unicode.GetBytes(StrJson),0) as TJSONObject;
  //    jo := TJSONObject.ParseJSONValue(TEncoding.ASCII.GetBytes(StrJson),0) as TJSONObject;
  jo := TJSONObject.ParseJSONValue(TEncoding.UTF8.GetBytes(StrJson),0) as TJSONObject;    

  Memo1.Clear;
  Memo1.Lines.Add(jo.ToString);

  RestRequest1.ClearBody;
  RestRequest1.Method := rmPost;
  RestResponse1.ResetToDefaults;
  RestRequest1.AddBody(jo);
  RestRequest1.Execute;   // ==> error: No mapping for the Unicode character exists in the target multi-byte code page
end;

SERVER SIDE code:

procedure TMytestResource1.MytestPost(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
var
  s : string;
  i : integer;
  jo : TJSONObject;
begin
  jo := TJSONObject.Create;
  jo.AddPair('Response Line 1','Apple is maçã');
  jo.AddPair('Response Line 2','Foot is pé ');
  jo.AddPair('Response Line 3','There is lá');
  jo.AddPair('Exceção  Line 3',TJsonString.Create('Exception is exceção'));
  //s := jo.ToString;  at this point the characters has accents
  AResponse.Body.SetValue(jo, True);
end;

Configuration of REST components is as follows :

RestClient1.Accept          := 'application/json, text/plain; q=0.9, text/html;q=0.8,';
RestClient1.AcceptCharset   := 'utf-8;q=0.8';
RestClient1.AcceptEnconding := 'utf-8';
RestClient1.FallbackCharsetEncoding := 'utf-8';
RestClient1.ContentType    := 'application/json'
    
RestRequest1.Accept          := 'application/json, text/plain; q=0.9, text/html;q=0.8,'
RestRequest1.AcceptCharset   := 'utf-8;q=0.8';
    
RestResponse1.ContentEncoding := '';
RestResponse1.ContentType := '';

New Server Side Code (worked fine):

procedure TMytestResource1.CadastraUser(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
var
  s : string;
  i : integer;
  jo : TJSONObject;
  Strm : TStringStream;
begin
  jo := TJSONObject.Create;
  jo.AddPair('Response Line 1','Apple  is maçã');
  jo.AddPair('Response Line 2','Foot   is pé');
  jo.AddPair('Response Line 3','There  is lá');
  jo.AddPair('Response Line 4','Useful is útil');

  //AResponse.Headers.SetValue('Content-Type', 'application/json; charset=utf-8');  ==> This line does not make any effect on response

  try
    // Strm := TStringStream(jo.ToJSON, TEncoding.UTF8); ==> does not work.
    Strm := TStringStream.Create(jo.ToJSON, TEncoding.UTF8);
    // AResponse.Body.SetStream(Strm, 'application/json; charset=utf-8', true); ==> This line causes an error on VCL WebClient during RestRequest.Execute() method , error is "Invalid enconding name."

    AResponse.Body.SetStream(Strm, 'application/json', true); // this works fine.
  finally
    jo.Free;
  end;   
end;

So now, new questions arise :

  1. Why does this same program work fine in Delphi 10.3.1 Tokyo under Windows 7, but now in Delphi 10.4 Sydney (patches 1,2,3) on Windows 10 it requires UTF-8 encoding? Is it a Delphi 10.4 issue? Is it a Windows 10 issue?

  2. In my original server side code, I have many Endpoints sending responses using the command AResponse.Body.SetValue(myJSONObject, True); Should I replace all of them by the two new commands?

    Strm := TStringStream.Create(jo.ToJSON, TEncoding.UTF8);
    AResponse.Body.SetStream(Strm, 'application/json', true);
    

Code of REST.Client unit where the error is occuring :

Procedure TCustomRestRequest.Execute 

...
              if LMimeKind <> TMimeTypes.TKind.Binary then
              begin
                LEncoding := TEncoding.GetEncoding(FClient.FallbackCharsetEncoding);  //==> This line is returning nil, though FClient.FallbackCharsetEncoding is filled with 'utf-8'
                LContentIsString := True;
              end;
            end
            else
            begin
              // Even if no fallback, handle some obvious string types
              if LMimeKind = TMimeTypes.TKind.Text then
                LContentIsString := True;
            end;
          end;
          if LContentIsString then
            LContent := FClient.HTTPClient.Response.ContentAsString(LEncoding); // ==> this line is generating the error 
        finally
          LEncoding.Free;
        end;
...
0

There are 0 answers