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;
});
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
How to Update Textbox in Form1 from Form2
Escape Command Line Arguments in C#
Difference Between Parameters.Add(String, Object) and Parameters.Addwithvalue
Parsing JSON Object with Variable Properties into Strongly Typed Object
.Net Core 3.0 Possible Object Cycle Was Detected Which Is Not Supported
Deserialize JSON Array Stream One Item at a Time
Filenotfoundexception in Applicationsettingsbase
Unique Random String Generation
Order of Items in Classes: Fields, Properties, Constructors, Methods
Quick and Simple Hash Code Combinations
How to Use Non-Thread-Safe Async/Await APIs and Patterns with ASP.NET Web API
Databinding to List - See Changes of Data Source in Listbox, Combobox
How to Convert a Timespan to a Formatted String