Click here to Skip to main content
15,311,561 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
I'm writing code for a console app that sends an HttpPostRequest to a WebAPI that will later send emails and text messages to a group of people. This information is stored as a JSON string on the console app and passed into the WebAPI. When posting, I receive StatusCode 200 indicating a successful operation, but when I check the API, I see that the value passed in is "null". Can someone tell me why this is? I have included the code for the console app and WebAPI.

What I have tried:

WebAPI Controller:
C#
[ApiController]
[Route("[controller]")]
public class GeneratorStatusController : ControllerBase
{
    Emails emailList = new Emails();
    public GeneratorStatusController(IGeneratorService generatorService)
    {
        this.generatorService = generatorService;
    }

    static List<string> strings = new List<string>()
    {
        "value0", "value1", "value2"
    };
    private readonly IGeneratorService generatorService;

    [HttpGet]
    public List<string> GetString()
    {
        return strings;
    }

    [HttpPost]
    public List<string> PostString(string input)
    {
        Console.WriteLine(input);

        // Send Emails Placeholder
        strings.Add(input); // When adding it to "strings", the value is null
        return strings;
    }
}
Console App that sends a post request:
C#
static async Task SendPost(string machineName, List<string> emailAddresses, List<string> phoneNumbers)
{
    string url = "https://localhost:44312/GeneratorStatus/";
    HttpClient client = new HttpClient();

    string name = JsonConvert.SerializeObject(machineName);
    string emails = JsonConvert.SerializeObject(emailAddresses);
    string phones = JsonConvert.SerializeObject(phoneNumbers);

    var jsonMessage = JsonConvert.SerializeObject(new[] 
                     {JsonConvert.DeserializeObject(name),
                      JsonConvert.DeserializeObject(emails),
                      JsonConvert.DeserializeObject(phones) });

    Console.WriteLine(jsonMessage);

    var response = await client.PostAsync(url, new StringContent(jsonMessage, Encoding.UTF8, "application/json"));
    Console.WriteLine(response);
}
Posted
Updated 29-Sep-20 3:20am
v2

1 solution

You need to add the [FromBody] attribute to your input parameter:
C#
[HttpPost]
public List<string> PostString([FromBody] string input)
Model Binding in ASP.NET Core | Microsoft Docs[^]

You should also remove the extra serialization and deserialization from your calling method. There's no point serializing to JSON simply to deserialize again on the next line.

However, since the method input is a string, you will need to double-encode your request body. Otherwise, the media formatter will decode the supplied JSON, and then refuse to bind the string array to a string parameter.
C#
static async Task SendPost(string machineName, List<string> emailAddresses, List<string> phoneNumbers)
{
    string url = "https://localhost:44312/GeneratorStatus/";
    HttpClient client = new HttpClient();

    var jsonMessage = JsonConvert.SerializeObject(new[] 
    {
        machineName,
        emailAddresses,
        phoneNumbers
    });

    Console.WriteLine(jsonMessage);
    
    // Serialize it again so that the server will treat it as a string:
    jsonMessage = JsonConvert.SerializeObject(jsonMessage);
    Console.WriteLine(jsonMessage);

    var response = await client.PostAsync(url, new StringContent(jsonMessage, Encoding.UTF8, "application/json"));
    Console.WriteLine(response);
}

As mentioned in the solution to your previous question[^], you should really be using a strongly-typed model instead of passing a JSON string around.
   
v2
Comments
stevenlam505 29-Sep-20 9:30am
   
When I use [FromBody] I encounter status code 400. That was my original implementation.
Richard Deeming 29-Sep-20 9:43am
   
Since the API method is expecting a string, and you're sending a JSON-serialized object array, the media formatter won't be able to bind your parameter.

You'll need to serialize your parameter twice so that the media formatter deserializes the request body to a string.

Alternatively, change the API's parameter to an object array, or use a strongly-typed model.
stevenlam505 29-Sep-20 10:05am
   
How would I change the parameters to an object array?
Richard Deeming 29-Sep-20 10:06am
   
[HttpPost]
public List<string> PostString([FromBody] object[] input)

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900