Home > front end >  Can't send via POST a nested JSON with null Subclass Net Core API
Can't send via POST a nested JSON with null Subclass Net Core API

Time:03-11

I want to send an object with subobjects as Json to my Net Core API using c#. This works if the sub-objects are filled. But as soon as the sub-object is null, it doesn't arrive at the controller. I received an error with status code 400.

    StatusCode: 400, ReasonPhrase: 'Bad Request', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:{  Date: Thu, 10 Mar 2022 09:40:25 GMT Server: Kestrel Content Length: 296 Content-Type: application/problem json; charset=utf-8 }}

I've been googling and trying a lot for the past 2 days. but unfortunately nothing works.

This is my model

   public class Location
   {
        [Key]
        public string Zipcode{ get; set; }
        public string LocationName { get; set; }
        public DateTime CreationDate{ get; set; }

        [ForeignKey("Street")]
        public string StreetID{ get; set; }
        public virtual Street Street{ get; set; }
    }

    public class Street
    {
        [Key]
        public string StreetName { get; set; }
    }

This is my Reqeust

            HttpClient httpClient = new HttpClient();
            string requestUri = "https://localhost:5001/Customers/CreateLocation";
            
            var json = JsonConvert.SerializeObject(location);
            var buffer = System.Text.Encoding.UTF8.GetBytes(json);
            var byteContent = new ByteArrayContent(buffer);
            byteContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
            var response = await httpClient.PostAsync(requestUri, byteContent);
            string result = response.Content.ReadAsStringAsync().Result;

This is my Controller

        [HttpPost]
        [Route("CreateLocation")]
        public IActionResult CreateOrt(Location location)
        {
            location = KundenRepositorie.CreateLocation(Bankdaten_DB, location);
            return CreatedAtAction("GetCustomerByID", new { id = location.Zipcode}, location);
        }

I have already added the following to Programm.cs

builder.Services.AddControllers().AddNewtonsoftJson();
builder.Services.AddControllers().AddJsonOptions(options =>
{
   options.JsonSerializerOptions.DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull;
});

This Json Works fine and arrives at the controller

{"Zipcode":"89898",
 "LocationName ":"MyCity",
 "CreationDate":"2022-03-10T11:01:25.9840573 01:00",
 "StreedID":"Am Dorf",
 "Street":
          {"StreetName ":"Am Dorf",
            "Kunden":null}
}

But here I get the error message and it doesn't arrive

{"Zipcode":"89898",
    "LocationName":"MyCity",
    "CreationDate":"2022-03-10T11:12:39.8402702 01:00",
    "StreedID":null,
    "Street":null}

I am very grateful for any help tip. Maybe I'm doing something fundamentally wrong. I'm here learning for myself and experimenting with the API and the database model to gain experience.

CodePudding user response:

since you are using net 6 , you have to make everything nullable, this is why you have the error you can try this

public class Location
   {
        .....
        public string? StreetID{ get; set; }
        public virtual Street? Street{ get; set; }
    }

but I recommend you to fix everything, by removing nullable from your project properties, otherwise it will be repeating and repeating

<PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <!--<Nullable>enable</Nullable>-->
    <ImplicitUsings>enable</ImplicitUsings>
  </PropertyGroup>

then fix the program, you added controllers twice, it should be once

builder.Services.AddControllers()
.AddNewtonsoftJson(options =>
  options.SerializerSettings.ContractResolver =
        new CamelCasePropertyNamesContractResolver());

then fix your http request , you don't need any byte array, since you are sending json

    string requestUri = "https://localhost:5001/Customers/CreateLocation";
using HttpClient client = new HttpClient();

client.DefaultRequestHeaders.Accept.Clear();
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

 var json = JsonConvert.SerializeObject(location);
var content = new StringContent(json, UTF8Encoding.UTF8, "application/json");    
  
var response = await client.PostAsync(requestUri, content);     

if (response.IsSuccessStatusCode)
    {
        var stringData = await response.Content.ReadAsStringAsync();
        var result = JsonConvert.DeserializeObject<object>(stringData);
    }   

and fix the post action

         [HttpPost]
        [Route("CreateLocation")]
        public IActionResult CreateOrt([FromBody] Location location)

CodePudding user response:

You need to add FromBody attribute to get your data for the POST operation:

[HttpPost]
[Route("CreateLocation")]
public IActionResult CreateOrt([FromBody]Location location)

You can read more on parameter binding on MSDN docs.

  • Related