Skip to content

POST with JSON string not working #16

Open
@bclewi

Description

@bclewi

Thank you for your work on this awesome library!

Should we be able to pass JSON strings in the Body of a POST request? Am I not using the Client correctly?

  • I get a 200 ResponseCode in the README example.
  • I get a 200 ResponseCode on POST when passing Body a variable path to a valid DUT.
  • I get a 400 ResponseCode on POST when passing Body an empty string (Body := '') because my endpoint validates the request.
  • I get a 200 ResponseCode when using curl with valid JSON data.
  • I do not get a ResponseCode on POST when passing Body a JSON string with valid JSON data.

Failing example with JSON string

MAIN.TcPOU

Client : HttpClient;
Execute : BOOL := TRUE;
HasError : BOOL;
ErrorId : UDINT;
Client(
	Execute := Execute,
	Address := 'https://www.fake-example.com/ExampleController/Post',
	CallMethod := 'POST',
	Body := '{"stringProperty": "string", "dintProperty": 1, "arrayProperty": ["string"]}',
	ResponseCode := 'GVL.ResponseCode', // This is not updated from the default value of 0.
	Response := '',
	HasError => HasError, // No error returned
	ErrorId => ErrorId);

IF Execute THEN
        Execute := FALSE;
END_IF

GVL.TcGVL

{attribute 'qualified_only'}
VAR_GLOBAL
    ResponseCode : INT;
END_VAR

header.json

{
  "Accept": "*/*",
  "Content-Type": "application/json"
}

The .NET/C# endpoint responds to POST with 200 if it receives a valid request body

ExampleController.cs

namespace ExampleProject.API.Controllers;

[ApiController, Route("[controller]/[action]")]
public class ExampleController : ControllerBase
{
  // "/ExampleController/Post"
  [HttpPost]
  [ProducesResponseType(StatusCodes.Status200OK)]
  [ProducesResponseType(StatusCodes.Status400BadRequest)]
  public async Task<IActionResult> Post([FromBody] Request request) => return Ok();
}

Request.cs

namespace ExampleProject.API.Models;

public class Request
{
    // JSON must include this property with a non-empty string value.
    [Required(AllowEmptyStrings = false)]
    public string StringProperty { get; set; } = string.Empty;

    // JSON must include this property with any int value.
    [Required]
    public int DintProperty { get; set; }

    // JSON must include this property with 0 or more strings in an array.
    [Required]
    public IEnumerable<string> ArrayProperty { get; set; } = Enumerable.Empty<string>();
}

Working example with variable path

MAIN.TcPOU

Client : HttpClient;
Execute : BOOL := TRUE;
HasError : BOOL;
ErrorId : UDINT;
Client(
	Execute := Execute,
	Address := 'https://www.fake-example.com/ExampleController/Post',
	CallMethod := 'POST',
	Body := 'GVL.Body',
	ResponseCode := 'GVL.ResponseCode', // This is 200 on success.
	Response := '',
	HasError => HasError,
	ErrorId => ErrorId);

IF Execute THEN
        Execute := FALSE;
END_IF

GVL.TcGVL

{attribute 'qualified_only'}
VAR_GLOBAL
    Body : Body;
    ResponseCode : INT;
END_VAR

Body.TcDUT

TYPE Body :
STRUCT
    {attribute 'json' := 'stringProperty'}
    StringProperty : STRING := 'string';

    {attribute 'json' := 'dintProperty'}
    DintProperty : INT := 1;

    {attribute 'json' := 'arrayProperty'}
    ArrayProperty : ARRAY[0..9] OF STRING := ['string'];
END_STRUCT
END_TYPE

header.json

{
  "Accept": "*/*",
  "Content-Type": "application/json"
}

Why do I care about using a JSON string if the variable path to a DUT is working ok?

In my working example above, the DUT contains a property of type ARRAY[0..9] OF STRING, a static array, but the REST API endpoint takes in a dynamic array of strings, expected to vary with each call. For this use case, it is preferred to send:

{"stringProperty": "string", "dintProperty": 1, "arrayProperty": ["string"]}

instead of what the DUT deserializes to:

{"stringProperty": "string", "dintProperty": 1, "arrayProperty": ["string","","","","","","","","",""]}

Passing a JSON string to the HttpClient Body would be a workaround for all requests with dynamic arrays that do not serialize appropriately.

Metadata

Metadata

Assignees

Labels

enhancementNew feature or requestgood first issueGood for newcomersquestionFurther information is requested

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions