ASP.NET Core 2 API Post Objects Are Null

Asp.net Core 2 API POST Objects are NULL?

You need to include the [FromBody] attribute on the model:

[FromBody] MyTestModel model

See Andrew Lock's post for more information:

In order to bind the JSON correctly in ASP.NET Core, you must modify your action to include the attribute [FromBody] on the parameter. This tells the framework to use the content-type header of the request to decide which of the configured IInputFormatters to use for model binding.

As noted by @anserk in the comments, this also requires the Content-Type header to be set to application/json.

POST null because property type does not match?

When null is mapped to the bool, resulting in a type mismatch exception, it will cause the whole object become null.

If this api is 3.x, it will trigger 400. But in 2.x and 5.0, they have no exception. You can handle the null value through NewtonSoft.json.

A simple way to handel it with this configuration, it can assign a default value to bool, but it doesn't trigger exception.

In 2.x

services.AddMvc()
.AddJsonOptions(options=>
{
options.SerializerSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore;
});

5.0

services.AddControllers()
.AddNewtonsoftJson(option=>
{
option.SerializerSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore;
});

Sample Image

If must return an error, you have to use a custom model binding.

public class CustomBindClassBinder : IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{

var itemClass = new ItemClass();
using (var reader = new StreamReader(bindingContext.HttpContext.Request.Body))
{
var body = reader.ReadToEndAsync();
var mydata = JsonConvert.DeserializeObject<JObject>(body.Result);

if(mydata["isActive"].ToString()==""|| mydata["isActive"].ToString() == null)
{
bindingContext.Result= ModelBindingResult.Failed();
throw new Exception("isActive is not correct");
}
else
{
itemClass.Id = mydata["id"].ToString();
itemClass.Name = mydata["name"].ToString();
itemClass.Description = mydata["description"].ToString();
itemClass.IsActive = bool.Parse(mydata["isActive"].ToString());
bindingContext.Result = ModelBindingResult.Success(itemClass);
}
}
return Task.CompletedTask;
}
}

In action

    [HttpPost]
public async Task<IActionResult> Insert([FromBody][ModelBinder(typeof(CustomBindClassBinder))] ItemClass newItem)
{

return Ok(newItem);
}

Why are POST params always null in .NET Core API

You can't get two separate parameters from body, cause it is going to bind email and password as properties of the parameter, not exact parameters. You need to create an object, which defines properties with those names, and use that object in the parameter

class Login 
{
public string Email { get; set; }
public string Password { get; set; }
}

In the action method parameter

([FromBody]Login model)

FromBody in ASP.NET Core API returns null

You need to change all of your fields in the SupplierMaterialMaintenance class to the properties with getter and setter

public class SupplierMaterialMaintenance : IComparable<SupplierMaterialMaintenance>, IEquatable<SupplierMaterialMaintenance>
{
public Guid SupplierMaterialAssociationGuid { get; set; }
public int MinimumOrderQuantity { get; set; }
public Guid UnitOfMeasurementGuid { get; set; }
public int ConversionFactor { get; set; }
//goes like this...

You can take a look at Microsoft Documentation about Model Binding in .net-core

Can't send via POST a nested JSON with null Subclass Net Core API

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)

ASP.NET Core API POST parameter is always null

The problem is that the Content-Type is application/json, whereas the request payload is actually text/plain. That will cause a 415 Unsupported Media Type HTTP error.

You have at least two options to align then Content-Type and the actual content.

Use application/json

Keep the Content-Type as application/json and make sure the request payload is valid JSON. For instance, make your request payload this:

{
"cookie": "=sec_session_id=[redacted]; _ga=[redacted]; AWSELB=[redacted]"
}

Then the action signature needs to accept an object with the same shape as the JSON object.

public class CookieWrapper
{
public string Cookie { get; set; }
}

Instead of the CookieWrapper class, or you can accept dynamic, or a Dictionary<string, string> and access it like cookie["cookie"] in the endpoint

public IActionResult GetRankings([FromBody] CookieWrapper cookie)

public IActionResult GetRankings([FromBody] dynamic cookie)

public IActionResult GetRankings([FromBody] Dictionary<string, string> cookie)

Use text/plain

The other alternative is to change your Content-Type to text/plain and to add a plain text input formatter to your project. To do that, create the following class.

public class TextPlainInputFormatter : TextInputFormatter
{
public TextPlainInputFormatter()
{
SupportedMediaTypes.Add("text/plain");
SupportedEncodings.Add(UTF8EncodingWithoutBOM);
SupportedEncodings.Add(UTF16EncodingLittleEndian);
}

protected override bool CanReadType(Type type)
{
return type == typeof(string);
}

public override async Task<InputFormatterResult> ReadRequestBodyAsync(
InputFormatterContext context,
Encoding encoding)
{
string data = null;
using (var streamReader = context.ReaderFactory(
context.HttpContext.Request.Body,
encoding))
{
data = await streamReader.ReadToEndAsync();
}

return InputFormatterResult.Success(data);
}
}

And configure Mvc to use it.

services.AddMvc(options =>
{
options.InputFormatters.Add(new TextPlainInputFormatter());
});

See also

https://github.com/aspnet/Mvc/issues/5137



Related Topics



Leave a reply



Submit