.NET Core API gets null from Angular POST - c#

I'm trying to POST data from Angular to my .NET Core API, but the incoming data is always null. See my code:
Here is my POST from Angular:
public insertCategory(categoryToInsert: ICategoryDTO): Observable<ICategoryDTO> {
const body: string = JSON.stringify(categoryToInsert);
return this.httpClient.post<ICategoryDTO>(this.apiURL + 'Categories/new', categoryToInsert);
}
ICategoryDTO being an object like this:
export interface ICategoryDTO {
Id: number;
Name: string;
}
export default ICategoryDTO;
//exemple object:
{Id: null, Name: "yyuyuy"}
This is what my API endpoint looks like on the .NET Core side:
[HttpPost("new")]
[ProducesResponseType(201)]
[ProducesResponseType(400)]
[ProducesResponseType(409)]
[ProducesResponseType(500)]
public IActionResult CreateWithAuthor([FromBody] CategoryDTO data)
{
var a = 1;
return Ok(this._iCategoryBusiness.CreateWithAuthor(data));
}
CategoryDTO being defined by this class:
using System;
namespace Back.DTO
{
public class CategoryDTO
{
public int Id { get; set; }
public string Name { get; set; }
}
}
My problem: I have a breakpoint at var a = 1 and on that breakpoint data is always null when performing the post from my front-end. Doing it from Swagger works.
What I have tried: I have tried to stringify my object before passing it, which did nothing. I have also tried to pass a header along, both with stringified and non-stringified object, which did not work either. I changed the ICategoryDTO Id type from string to number but that did nothing.
Here's the header I have tried:
header = new HttpHeaders()
.set('Content-type', 'application/json');
With a request like this:
public insertCategory(categoryToInsert: ICategoryDTO): Observable<ICategoryDTO> {
const body: string = JSON.stringify(categoryToInsert);
return this.httpClient.post<ICategoryDTO>(this.apiURL + 'Categories/new', body, {headers: this.header});
}
Didn't work, same result.
Don't know what I'm doing wrong.

I fixed it by making my Id parameter not null, but 0 instead. I guess this makes sense because it isn't nullable on the .NET end. This took me two hours.

Related

can we pass array to post request in react using axios?

let assume,
companyDetail is an object, and I have to pass list of company details to API.
so can I d sent array of object in post request like this:-
axios.post("",);
note API is made in ASP.NET Core Web API.
what type of data can we send ?
You can send an array of objects as long as the endpoint expect to receive this type of data.
With axios:
const companyDetails = [
{ ... },
{ ... },
{ ... },
];
axios.post("https://myapi.com/companydetails", companyDetails)
.then(response => {
console.log(response.data);
})
.catch(error => {
console.log(error);
});
Yes you can pass data as array of object companyDetail but its depends on how API request body is created in backend. If API wants request body in some other custom variable lets as reqBody the you have to assign your companyDetail to reqBody
axios.post("endpoint", {reqBody: companyDetail})
If API wants request body in companyDetail itself then:
axios.post("endpoint", {companyDetail})
CompanyDetail is an object, and I have to pass list of company details
to API. so can I d sent array of object in post request like this:-
axios.post("",);Note API is made in ASP.NET Core Web API. What type of
data can we send ?
Well, to begin with your first concern, yes we definitely can post list of object as axios.post("",) fashion. Considering your scenario we can write that snippet as following:
Let's assume, we have model as below:
Model:
public class CompanyDetails
{
public int CompanyId { get; set; }
public string Name { get; set; }
public string Email { get; set; }
}
Asp.net core Web API:
[Route("api/[controller]")]
[ApiController]
public class AxiosWebApiController : ControllerBase
{
[HttpPost]
[Route("CompanyDetails")]
public async Task<IActionResult> CompanyDetails(List<CompanyDetails> companyDetails)
{
// Do whatever you like here
return Ok(companyDetails);
}
}
What type of data can we send ?
Well, its up to you, if your controller accept list of object as Model just like this List<CompanyDetails> companyDetails then you can do as following.
Axios Request:
#section Scripts
{
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
const CompanyId = "CompnayId:";
const Name = "Name:";
const Email = "Email:";
const companyDetails = [];
for (let i = 1; i <= 10; i++) {
const companyObject = {
CompanyId: CompanyId + i,
Name: Name + i,
Email: Email + i
}
companyDetails.push(companyObject);
}
console.log(companyDetails);
axios.post("http://localhost:5094/api/AxiosWebApi/CompanyDetails", companyDetails);
</script>
}
Note: If your controller accept [FromForm] then append as FormData() just like formData.append("CompanyId", 1); then push to your array object.
In addition, please check your browser console if the object posted accordingly as following:
Output:

AWP.Net Web API Post object always empty [duplicate]

I have a Web API service call that updates a user's preferences. Unfortunately when I call this POST method from a jQuery ajax call, the request parameter object's properties are always null (or default values), rather than what is passed in. If I call the same exact method using a REST client (I use Postman), it works beautifully. I cannot figure out what I'm doing wrong with this but am hoping someone has seen this before. It's fairly straightforward...
Here's my request object:
public class PreferenceRequest
{
[Required]
public int UserId;
public bool usePopups;
public bool useTheme;
public int recentCount;
public string[] detailsSections;
}
Here's my controller method in the UserController class:
public HttpResponseMessage Post([FromBody]PreferenceRequest request)
{
if (request.systemsUserId > 0)
{
TheRepository.UpdateUserPreferences(request.UserId, request.usePopups, request.useTheme,
request.recentCount, request.detailsSections);
return Request.CreateResponse(HttpStatusCode.OK, "Preferences Updated");
}
else
{
return Request.CreateErrorResponse(HttpStatusCode.NotAcceptable, "You must provide User ID");
}
}
Here's my ajax call:
var request = {
UserId: userId,
usePopups: usePopups,
useTheme: useTheme,
recentCount: recentCount,
detailsSections: details
};
$.ajax({
type: "POST",
data: request,
url: "http://localhost:1111/service/User",
success: function (data) {
return callback(data);
},
error: function (error, statusText) {
return callback(error);
}
});
I've tried setting the dataType & contentType to several different things ('json', 'application/json', etc) but the properties of the request object are always defaulted or null. So, for example, if I pass in this object:
var request = {
UserId: 58576,
usePopups: false,
useTheme: true,
recentCount: 10,
detailsSections: ['addresses', 'aliases', 'arrests', 'events', 'classifications', 'custody', 'identifiers', 'phone', 'remarks', 'watches']
}
I can see a fully populated request object with the valid values as listed above. But in the Web API controller, the request is there, but the properties are as follows:
UserId: 0,
usePopups: false,
useTheme: false,
recentCount: 0,
detailsSections: null
FYI - I'm not doing ANY ASP.Net MVC or ASP.NET pages with this project, just using the Web API as a service and making all calls using jQuery $.ajax.
Any idea what I'm doing wrong here? Thanks!
UPDATE: I just want to note that I have many methods in this same Web API project in other controllers that do this exact same thing, and I am calling the exact same way, and they work flawlessly! I have spent the morning comparing the various calls, and there doesn't appear to be any difference in the method or the headers, and yet it just doesn't work on this particular method.
I've also tried switching to a Put method, but I get the exact same results - the request object comes in, but is not populated with the correct values. What's so frustrating is that I have about 20 controller classes in this project, and the Posts work in all of those...
This seems to be a common issue in regards to Asp.Net WebAPI.
Generally the cause of null objects is the deserialization of the json object into the C# object. Unfortunately, it is very difficult to debug - and hence find where your issue is.
I prefer just to send the full json as an object, and then deserialize manually. At least this way you get real errors instead of nulls.
If you change your method signature to accept an object, then use JsonConvert:
public HttpResponseMessage Post(Object model)
{
var jsonString = model.ToString();
PreferenceRequest result = JsonConvert.DeserializeObject<PreferenceRequest>(jsonString);
}
So there are 3 possible issues I'm aware of where the value does not bind:
no public parameterless constructor
properties are not public settable
there's a binding error, which results in a ModelState.Valid == false - typical issues are: non compatible value types (json object to string, non-guid, etc.)
So I'm considering if API calls should have a filter applied that would return an error if the binding results in an error!
Maybe it will help, I was having the same problem.
Everything was working well, and suddently, every properties was defaulted.
After some quick test, I found that it was the [Serializable] that was causing the problem :
public IHttpActionResult Post(MyComplexClass myTaskObject)
{
//MyTaskObject is not null, but every member are (the constructor get called).
}
and here was a snippet of my class :
[Serializable] <-- have to remove that [if it was added for any reason..]
public class MyComplexClass()
{
public MyComplexClass ()
{
..initiate my variables..
}
public string blabla {get;set;}
public int intTest {get;set;
}
I guess problem is that your controller is expecting content type of [FromBody],try changing your controller to
public HttpResponseMessage Post(PreferenceRequest request)
and ajax to
$.ajax({
type: "POST",
data: JSON.stringify(request);,
dataType: 'json',
contentType: "application/json",
url: "http://localhost:1111/service/User",
By the way creating model in javascript may not be best practice.
Using this technique posted by #blorkfish worked great:
public HttpResponseMessage Post(Object model)
{
var jsonString = model.ToString();
PreferenceRequest result = JsonConvert.DeserializeObject<PreferenceRequest>(jsonString);
}
I had a parameter object, which had a couple of native types and a couple more objects as properties. The objects had constructors marked internal and the JsonConvert.DeserializedObject call on the jsonString gave the error:
Unable to find a constructor to use for type ChildObjectB. A class
should either have a default constructor, one constructor with
arguments or a constructor marked with the JsonConstructor attribute.
I changed the constructors to public and it is now populating the parameter object when I replace the Object model parameter with the real object. Thanks!
I know, this is a bit late, but I just ran into the same issue. #blorkfish's answer worked for me as well, but led me to a different solution. One of the parts of my complex object lacked a parameter-less constructor. After adding this constructor, both Put and Post requests began working as expected.
I have also facing this issue and after many hours from debbug and research can notice the issue was not caused by Content-Type or Type $Ajax attributes, the issue was caused by NULL values on my JSON object, is a very rude issue since the POST neither makes but once fix the NULL values the POST was fine and natively cast to my respuestaComparacion class here the code:
JSON
respuestaComparacion: {
anioRegistro: NULL, --> cannot cast to BOOL
claveElector: NULL, --> cannot cast to BOOL
apellidoPaterno: true,
numeroEmisionCredencial: false,
nombre: true,
curp: NULL, --> cannot cast to BOOL
apellidoMaterno: true,
ocr: true
}
Controller
[Route("Similitud")]
[HttpPost]
[AllowAnonymous]
public IHttpActionResult SimilitudResult([FromBody] RespuestaComparacion req)
{
var nombre = req.nombre;
}
Class
public class RespuestaComparacion
{
public bool anioRegistro { get; set; }
public bool claveElector { get; set; }
public bool apellidoPaterno { get; set; }
public bool numeroEmisionCredencial { get; set; }
public bool nombre { get; set; }
public bool curp { get; set; }
public bool apellidoMaterno { get; set; }
public bool ocr { get; set; }
}
Hope this help.
I came across the same issue. The fix needed was to ensure that all serialize-able properties for your JSON to parameter class have get; set; methods explicitly defined. Don't rely on C# auto property syntax! Hope this gets fixed in later versions of asp.net.
A bit late to the party, but I had this same issue and the fix was declaring the contentType in your ajax call:
var settings = {
HelpText: $('#help-text').val(),
BranchId: $("#branch-select").val(),
Department: $('input[name=departmentRadios]:checked').val()
};
$.ajax({
url: 'http://localhost:25131/api/test/updatesettings',
type: 'POST',
data: JSON.stringify(settings),
contentType: "application/json;charset=utf-8",
success: function (data) {
alert('Success');
},
error: function (x, y, z) {
alert(x + '\n' + y + '\n' + z);
}
});
And your API controller can be set up like this:
[System.Web.Http.HttpPost]
public IHttpActionResult UpdateSettings([FromBody()] UserSettings settings)
{
//do stuff with your UserSettings object now
return Ok("Successfully updated settings");
}
In my case problem was solved when i added
get{}set{}
to parameters class definition:
public class PreferenceRequest
{
public int UserId;
public bool usePopups {get; set;}
public bool useTheme {get; set;}
public int recentCount {get; set;}
public string[] detailsSections {get;set;}
}
enstead of:
public class PreferenceRequest
{
[Required]
public int UserId;
public bool usePopups;
public bool useTheme;
public int recentCount;
public string[] detailsSections;
}
As this issue was troubling me for almost an entire working day yesterday, I want to add something that might assist others in the same situation.
I used Xamarin Studio to create my angular and web api project. During debugging the object would come through null sometimes and as a populated object other times. It is only when I started to debug my project in Visual Studio where my object was populated on every post request. This seem to be a problem when debugging in Xamarin Studio.
Please do try debugging in Visual Studio if you are running into this null parameter problem with another IDE.
Today, I've the same problem as yours. When I send POST request from ajax the controller receive empty object with Null and default property values.
The method is:
[HttpPost]
public async Task<IActionResult> SaveDrawing([FromBody]DrawingModel drawing)
{
try
{
await Task.Factory.StartNew(() =>
{
//Logic
});
return Ok();
}
catch(Exception e)
{
return BadRequest();
}
}
My Content-Type was correct and everything else was correct too. After trying many things I found that sending the object like this:
$.ajax({
url: '/DrawingBoard/SaveDrawing',
type: 'POST',
contentType: 'application/json',
data: dataToPost
}).done((response) => { });
Won't work, but sending it like this instead worked:
$.ajax({
url: '/DrawingBoard/SaveDrawing',
type: 'POST',
contentType: 'application/json',
data: JSON.stringify(dataToPost)
}).done((response) => { });
Yes, the missing JSON.stringify() caused the whole issue, and no need to put = or anything else as prefix or suffix to JSON.stringify.
After digging a little bit. I found that the format of the request payload completely different between the two requests
This is the request payload with JSON.stringify
And this is the request payload without JSON.stringify
And don't forget, when things get magical and you use Google Chrome to test your web application. Do Empty cache and hard reload from time to time.
I ran into the same issue, the solution for me was to make certain the types of my class attributes matched the json atributes, I mean
Json: "attribute": "true"
Should be treated as string and not as boolean, looks like if you have an issue like this all the attributes underneath the faulty attribute will default to null
I ran into the same problem today as well. After trying all of these, debugging the API from Azure and debugging the Xamarin Android app, it turns out it was a reference update issue. Remember to make sure that your API has the Newtonsoft.JSON NUGET package updated (if you are using that).
My issue was not solved by any of the other answers, so this solution is worth consideration:
I had the following DTO and controller method:
public class ProjectDetailedOverviewDto
{
public int PropertyPlanId { get; set; }
public int ProjectId { get; set; }
public string DetailedOverview { get; set; }
}
public JsonNetResult SaveDetailedOverview(ProjectDetailedOverviewDto detailedOverview) { ... }
Because my DTO had a property with the same name as the parameter (detailedOverview), the deserialiser got confused and was trying to populate the parameter with the string rather than the entire complex object.
The solution was to change the name of the controller method parameter to 'overview' so that the deserialiser knew I wasn't trying to access the property.
I face this problem this fix it to me
use attribute [JsonProperty("property name as in json request")]
in your model by nuget package newton
if you serializeobject call PostAsync only
like that
var json = JsonConvert.SerializeObject(yourobject);
var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json");
var response = await client.PostAsync ("apiURL", stringContent);
if not work remove [from body] from your api
HttpGet
public object Get([FromBody]object requestModel)
{
var jsonstring = JsonConvert.SerializeObject(requestModel);
RequestModel model = JsonConvert.DeserializeObject<RequestModel>(jsonstring);
}
public class CompanyRequestFilterData
{
public string companyName { get; set; }
public string addressPostTown { get; set; }
public string businessType { get; set; }
public string addressPostCode{ get; set; }
public bool companyNameEndWith{ get; set; }
public bool companyNameStartWith{ get; set; }
public string companyNumber{ get; set; }
public string companyStatus{ get; set; }
public string companyType{ get; set; }
public string countryOfOrigin{ get; set; }
public DateTime? endDate{ get; set; }
public DateTime? startDate { get; set; }
}
webapi controller
[HttpGet("[action]"),HttpPost("[action]")]
public async Task<IEnumerable<CompanyStatusVm>> GetCompanyRequestedData(CompanyRequestFilterData filter)
{}
jsvascript/typescript
export async function GetCompanyRequesteddata(config, payload, callback, errorcallback) {
await axios({
method: 'post',
url: hostV1 + 'companydata/GetCompanyRequestedData',
data: JSON.stringify(payload),
headers: {
'secret-key': 'mysecretkey',
'Content-Type': 'application/json'
}
})
.then(res => {
if (callback !== null) {
callback(res)
}
}).catch(err => {
if (errorcallback !== null) {
errorcallback(err);
}
})
}
this is the working one c# core 3.1
my case it was bool datatype while i have changed string to bool [companyNameEndWith] and [companyNameStartWith] it did work. so please check the datatypes.

How to receive both File and data POSTed to an ASP.net core 2.1 Web-API endpoint

I'm trying to upload a file and some data (list of objects) to an ASP.net core 2.1 web-api endpoint.
This code below generates and sends the expected payload correctly:
const formData = new FormData()
formData.append('file', this.file)
formData.append('data', JSON.stringify(this.mappings))
axios.post('upload', formData)
// {headers: {'content-type': 'multipart/form-data'}} optional ???
The payload looks like this: (as seen in chrome dev-tools, network tab)
------WebKitFormBoundarydAP5tYG5GcFa4ivU
Content-Disposition: form-data; name="file"; filename="Master-List.xls"
Content-Type: application/vnd.ms-excel
------WebKitFormBoundarydAP5tYG5GcFa4ivU
Content-Disposition: form-data; name="data"
[{"required":true,"type":"field","value":"code","col":1,"text":"Item Code"},{"required":true,"type":"field","value":"name","col":2,"text":"Description"},{"required":true,"type":"field","value":"barcode","col":3,"text":"Barcode"},{"type":"field","value":"category","col":null,"text":"Category"},{"type":"field","value":"unit","col":null,"text":"Unit"},{"type":"location","value":1,"col":6,"text":"Store 1"}]
------WebKitFormBoundarydAP5tYG5GcFa4ivU--
The Web-api endpoint looks like this:
[HttpPost]
[Route("upload")]
//[Consumes("multipart/form-data")]
public Task<ActionResult> _upload([FromForm] Upload obj)
{
// do something
return Ok();
}
public class Upload
{
public Field[] data { get; set; }
public IFormFile file { get; set; }
}
public class Field
{
public int col { get; set; }
public string type { get; set; }
public string value { get; set; }
}
I am able to receive the file, but the data is always empty.
Please what am I missing?
Although there appears to be no out-of-the-box solution for sending JSON data to an ASP.NET Core MVC endpoint, it is possible to to format the data as a set of key-value pairs that will be parsed into your Fields[] as expected. It looks a little bit like this (name = value):
data[<index>][<key>] = value
Here's a code sample that builds up the FormData using explicit property keys:
for (let i = 0; i < this.mappings.length; i++) {
formData.append(`data[${i}][col]`, this.mappings[i].col);
formData.append(`data[${i}][type]`, this.mappings[i].type);
formData.append(`data[${i}][value]`, this.mappings[i].value);
}
This builds something that looks a bit like this:
data[0][col] = value
data[0][type] = value
data[0][value] = value
Here's an extended code sample that iterates over the properties, rather than using explicit keys:
for (let i = 0; i < this.mappings.length; i++) {
for (let k in this.mappings[i]) {
formData.append(`data[${i}][${k}]`, this.mappings[i][k]);
}
}
This last sample assumes that you want all iterable properties of each mapping - there are a number of different ways to do this in JavaScript that I will not enumerate here. If your mapping is a simple object, the code I've provided should suffice.
Overall, this is more verbose both in the code and in the number of parts being send to the ASP.NET Core MVC endpoint. The benefit is that the endpoint can just receive a strongly-typed model without having to perform any extra parsing of JSON, etc.
Not ideal, but this modification works
public class Upload
{
public string data { get; set; }
public IFormFile file { get; set; }
}
[HttpPost]
[Route("upload")]
[Consumes("multipart/form-data")]
public async Task<ActionResult> _upload([FromForm] Upload o)
{
List<Field> x = JsonConvert.DeserializeObject<List<Field>>(o.data);
return Ok();
}

trying to receive JSON as a JObject

I am trying to bring in JSON data into my method. I am using Postman to send my data.
An example of my JSON is...
{"FieldData" : {"name": "david"}, "Project" : 20, "Version" : 1}
My model is
public class IncomingFormData
{
public JObject FieldData { get; set; }
public int Project { get; set; }
public int Version { get; set; }
}
My method is
[HttpPost]
public void SaveFormData(IncomingFormData FieldData)
{
string myField = FieldData.FieldData.ToString();
}
I am getting null in FieldData.FieldData and the Project and Version are showing 0.
In my earlier version that worked, I had...
An example of my JSON is...
{FieldData : '{"name": "david"}', "Project" : 20, "Version" : 1}
[HttpPost]
public void SaveFormData(string FieldData, int Project, int Version)
{
string myField = FieldData;
}
Unfortunately for me, in this version, if the value of one of the FieldData objects has an apostrophe in it, it fails. (This is correct according to the RFC).
So, I had to rewrite it.
Now, I can't get anything coming in from Postman. The method is called but nothing coming in.
Postman has Accept application/json and content-type application/json set.
Thank you.
This is not really the way I wanted to do this, but hey, it works.
My original method was in a regular MVC controller. When I tried to send the JSON, I was getting the error Cannot create abstract class
However, creating an api controller instead, with pretty much the same signature JObject FieldData and from there, passing into my regular controller, it just works.
The code below is in the api controller.
public JsonResult Post([FromBody]JObject FieldData)
{
//string myData = FieldData.ToString();
FormsController form = new FormsController();
return form.SaveFormData(FieldData);
}
Try pass this: {"IncomingFormData":{"FieldData" : {"name": "david"}, "Project" : 20, "Version" : 1}}

OWIN ApiController access to the request body/stringified JSON

This is in OWIN & .Net 4.5.2
Using debug I'm proving this controller's method is being called by the web request.
My thing is the request body contains a JSON stringified object:
"{ 'id':'12', 'text1':'hello', 'test2':'world' }"
Which is applicably encoded as it is transferred on the line.
I've tried so many things I'm so confused now.
How do I get the decoded string so I can JSON.Parse() that or better yet get .Net to just given me an object?
In one version (long ago now) I had a defined type for this object. If I need that great, not a high challenge. But if I only have the JSON object from the string that's fine too.
public class cController : ApiController {
[HttpPut]
public string put(string id) {
var bdy = this.Request.Content;
//Console.WriteLine("PUT containers {0}", body);
return string.Empty;
}
}
In case it helps, the bdy.ContentReadStream is null. I don't know if this is good, bad, or important. Maybe Request.Content isn't the way to go but seems to me like if I'm going to read the body as a stream then it shouldn't be null.
I also tried working through System.Web.HttpContext. If that is somehow the answer I have no problem going back to that. But I couldn't find the secret sauce.
Pass the desired model as a parameter to the action and the frame work should be able to parse it provided it is valid JSON
public class cController : ApiController {
[HttpPut]
public IHttpActionResult Put(string id,[FromBody] Model body) {
if(ModelState.IsValue) {
return Ok(body.text1);
}
return BadRequest();
}
}
Where Model is defined as
public class Model {
public string id { get; set; }
public string text1 { get; set; }
public string test2 { get; set; }
}

Categories

Resources