0

I have a request object below:

public class SearchRequest
{
    [JsonProperty(PropertyName = "search_value")]
    public string Value { get; set; }
}

and a web api endpoint that expects

[HttpPost]
[Route("~/api/city/search")]
public SearchResponse Search(SearchRequest request)
{
    try
    {
        var result = _cityService.Search(request);

        return result;
    }
    catch (Exception ex)
    {
        throw ex;
    }
}

which I call using the following

var serialisedRequest = JsonConvert.SerializeObject(request);

which serialises the request like {"search_value":"test"}.

var content = new StringContent(serialisedRequest, Encoding.UTF8, "application/json");

using (var client = new HttpClient(new HttpClientHandler() { UseDefaultCredentials = true }))
{
    SetupHttpClient(client);

    var fullUrl = string.Format("{0}/{1}", baseUri, svcEndPoint);


    var request = new HttpRequestMessage { Content = content, Method = HttpMethod.Post, RequestUri = new System.Uri(fullUrl) };

    using (var result = await client.SendAsync(request))
    {
        if (result.IsSuccessStatusCode)
        {
            var content = await result.Content.ReadAsStringAsync();
            return JsonConvert.DeserializeObject<TResponse>(content);
        }
     }
 }

When I call the API and put a break point in the API controller, the value for Value is null.

Any reason why this would be?

11
  • Maybe you can try public SearchResponse Search([FromBody]SearchRequest request)? Commented Aug 17, 2021 at 12:18
  • @vernou Value still null. I think it has something to do with the jsonproperty Commented Aug 17, 2021 at 12:28
  • Possible, Newtonsoft.Json.JsonPropertyAttribute is used by the old deserializer json.net. But from ASP.NET Core 3, the default serializer is the new System.Text.Json. In this case, you need use [ System.Text.Json.Serialization.JsonPropertyNameAttribute](learn.microsoft.com/en-us/dotnet/api/…). Commented Aug 17, 2021 at 12:37
  • 1
    Like [JsonPropertyName("search_value")] public string Value { get; set; } Commented Aug 17, 2021 at 12:39
  • @vernou That's it. Looks like JsonPropertyName is the answer here Commented Aug 17, 2021 at 12:44

1 Answer 1

2

The attribute Newtonsoft.Json.JsonPropertyAttribute is used by the deserializer json.net.But from ASP.NET Core 3, the default deserializer is System.Text.Json. Then the expected attribute is System.Text.Json.Serialization.JsonPropertyNameAttribut.

In your case :

public class SearchRequest
{
    [JsonPropertyName("search_value")]
    public string Value { get; set; }
}

From @HenkHolterman comment, it seem the class SearchRequest is shared between the client and server. But the client use json.net and the server use System.Text.Json, then you need specify the two attribute like :

public class SearchRequest
{
    // To desierialize on the client by json.net
    [JsonProperty(PropertyName = "search_value")]
    // To desierialize on the server by System.Text.Json
    [JsonPropertyName("search_value")]
    public string Value { get; set; }
}

Other solution I advice, it's to use the same json library on the client and the server.

Sign up to request clarification or add additional context in comments.

5 Comments

Actually, I'm afraid I was wrong. I'm still getting null for my request object. Using above DOES pass {"Value":"test"} but the API still says that value is null
It only seems to work when I have both [JsonPropertyName("search_value")] and [JsonProperty(PropertyName = "search_value")] decorating the attribute.
Then you have System.Text.Json on one side and NewtonSoft on the other.
@HenkHolterman, I miss the point some code is shared... Can I edit my answer to integrate this information?
My comment was for @JamesS. The answer is OK.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.