I am unable to accomplish a successful ReactJs using Axios Post call where the data is passed to my asp.net core 2.2 web api. The call will only successfully hit my API endpoint when all compound word (last-name) properties are hyphenated, however the data does not get through. Only single word (company) properties receive the data. I believe it is because with the hyphens the properties no longer match. However, if the properties are not hyphenated I receive a 400 error or 415 error. When sending the call via Postman, where all properties are pascal cased, I don't have any issue at all.
I have tried many things to get it to work without solutions. I have added Json Attributes to my .net object properties. I have modified the attribute to also have the hyphens. I have tried changing both my properties in my react to single word and matching them with the Json attribute, e.i created vs CreatedDate. I have also pasted into my post method the exact same json object used in my PostMancall that was successful.
.net post
[HttpPost]
[Route("AddThreshold", Name = "AddThreshold")]
public ActionResult<ThresholdDTO> AddThreshold([FromBody] ThresholdDTO threshold)
{
var thr = _thresholdService.AddThreshold(threshold);
if (thr == null)
return NoContent();
return Ok(threshold);
}
const handleAddSubmit = e => {
e.preventDefault();
let current_datetime = new Date();
let formatted_date =
current_datetime.getFullYear() +
"-" +
(current_datetime.getMonth() + 1) +
"-" +
current_datetime.getDate() +
" " +
current_datetime.getHours() +
":" +
current_datetime.getMinutes() +
":" +
current_datetime.getSeconds();
console.log(location);
let threshold = JSON.stringify({
"Threshold-Id": "",
Company: company.toString(),
"Threshold-Type": thresholdType.toString(),
"Threshold-Value": thresholdValue.toString(),
"Account-Number": account.toString(),
"Location-Number": location == "undefined" ? "" : location.toString(),
"Expected-Amount": expectedAmount.toString(),
"Created-Date": formatted_date.toString(),
"Created-By": "System",
"Updated-Date": "1900-00-00 00:00:00.000",
"Updated-By": ""
});
Axios({
method: "post",
url: "https://localhost:44394/Threshold/AddThreshold/",
data: threshold,
headers: { "Content-Type": "application/json" }
})
.then(function(response) {
//handle success
console.log(threshold);
props.handleAddClose();
})
.catch(function(response) {
//handle error
console.log(threshold);
});
};
AccountNumber: "87605177 (CenturyLink)"
Company: "Deere Employees Credit Union"
CreatedBy: "System"
CreatedDate: "2019-10-27 16:1:51"
ExpectedAmount: "90000"
LocationNumber: "5000"
ThresholdId: ""
ThresholdType: "Invoice Processing"
ThresholdValue: "10"
UpdatedBy: ""
UpdatedDate: "1900-00-00 00:00:00.000"
The above object is exactly what postman is successful with but I receive a 400 code when using axios
The problem was my UpdatedDate value did not have an format acceptable to the Json Attribute causing the whole post to fail.
Related
I am trying to retrieve a document from a document warehouse then display that document in a new browser tab. I am using .net core 3.1 and react 16.
Here's what i have tried:
var link = '/Document/ViewDocument?docId=' + docId
window.open(link, "_blank");
This give an Unsupported media type error 415 and the request never hits the controller.
I tried using fetch and returning a filepath but this is restricted in the browser.
const response = await fetch('Document/ViewDocument', {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({ docId: docID })
});
const data = await response.json();
window.open('file:///' + data, "_blank"); //data = filepath
I've also tried fetch and returned a file from the controller but this didn't work either"
Here is my controller method:
[HttpGet]
[Route("ViewDocument")]
public async Task<IActionResult> ViewDocument(int docId)
{
//There is logic omitted here that actually retrieves the document from the document warehouse by docId.
string filePath = "C:\\inetpub\\wwwroot\\app\\tempfiles\\fileName";
string contentType = "application/pdf";
FileStream fs = new FileStream(filePath, FileMode.Open);
return File(fs, contentType);
}
In .net 4.7 i was able to do this:
var link = '#Url.Action("ViewDocument", "Document", new { area = "" })?docId=' + docId;
window.open(link, "_blank");
Can someone please help me figure out how to return a file from the controller and display that file in a new browser tab?
This actually does work:
var link = '/Document/ViewDocument?docId=' + docId
window.open(link, "_blank");
It didn't appear to be working initially because there was an error occuring in the document warehouse api.
So I have never post a data using FormData and multipart/form-data as Content-Type in my React project. But now I'm kinda forced by backend to send it this way since we have some images in payload.
The problem is that the whole data is a JS object and can be parsed to JSON, and nothing more. So how can I convert my JS object into a valid FormData that backend would accept it? Everything works without a problem in Postman, but in the app I always get the same error.
Here is some more detail:
The working Postman sample:
What I expect to be working (but obviously doesn't):
const createProd = () =>
HttpRequest.post('/api/prod', {
body: {
Product: {
title: 'Test Prod',
shop: null,
description: "My new ad's description",
category: { id: '5d8c6aa6fadeaf26b0194667' },
condition: 'USED'
}
});
HttpRequest is a helper function which uses ES6 fetch for requests.
I always get the same error: "Required request part 'Product' is not present" with/without JSON.stringify.
I even tried to create a sample FormData to at least change the error:
cont payload = new FormData();
payload.append('Product', {foo: 'bar'});
But still same error. I also copied the code which is generated by Postman. But still no chance.
I would be thankful if you share your suggestions or workarounds.
Thanks in advance.
const formData = new FormData();
const product = { //your product object };
formData.append('product', JSON.stringify(product));
const config = {
headers: {
'Content-Type': 'multipart/form-data; charset=utf-8; boundary="another cool boundary";'
}
};
axios.post(`/api/ads`, formData, config).then((res) => {
console.log(res);
}).catch(err => {
console.log(err);
});
Maybe you should set header.
Try this one. In my case I used Axios. It worked for me in my project.
There's this API:http://zssn-backend-example.herokuapp.com/api/, detailed here: http://zssn-backend-example.herokuapp.com/swagger-api/index.html#!/people/Api_People_index . I am trying to do a POST request on this endpoint "/people/{person_id}/properties/trade_item.json"(Make a trade transaction between survivors). On the Website for testing I filled the fields with the following data and got 204 response:
person_id:34e183a6-965e-4a61-8db5-5df9103f4d4b
consumer[name]: Person4
consumer[pick]: AK47:1;Campbell Soup:1
consumer[payment]: First Aid Pouch:2
I investigated a Little and got
this information
didn't understand the "PROPERTY[KEY]:VALUE" representation
When I try to the Request with this code, with the same values(by the way, the database of this API is cleared each 24 hours, so those value might not work, even if you do it in the right way):
this is My code:
async function handleTrade(e){
e.preventDefault();
const config = {
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
};
await api.post(
"/people/" + match.params.id + "/properties/trade_item.json",
{
person_id:match.params.id,
name: survivorRef.current,
pick: survivorItemsToPick,
payment: userItemsToPay,
},
config
);
And this is what I get:
Request:
request-description
Response:
response-description
How Can i make this request in the right way in order to get the same result as the first Image ?
You can use FormData to send the request, I made an example:
const data = new FormData();
data.append("customer[name]", "Person4");
data.append("customer[pick]", "AK47:1");
await api.post("/people/" + match.params.id + "/properties/trade_item.json", data, config)
I'm trying to post to my Laravel backend some data as 'offer' array:
That is how it looks in postman and works:
keys: offer[title], offer[description], offer[author_user_id]
now with axios I've tried something like:
offer: {
title: this.input.title,
description: this.input.description,
author_user_id: id,
}
tried also with:
[key=>val] and for example offer.title: value, but also failed.
How it should looks like?
EDIT:
this.axios.post('http://api.wip/api/offer/store', {
offer: {
title: this.input.title,
description: this.input.description,
author_user_id: id,
},
category: 2
}, {
headers: {
'Authorization': 'Bearer ' + token,
'Content-Type': 'application/x-www-form-urlencoded',
'X-Requested-With': 'application/json'
}
})
.then(function () {
})
.catch(function () {
});
In my console I can see it's sent as:
{"offer":{"title":"asd","description":"asd","author_user_id":"2"},"category":2}:
I recive 500 error from server with response from Laravel that it expects data to be array.
"message": "Argument 1 passed to Illuminate\\Database\\Eloquent\\Builder::create() must be of the type array, null given, called in D:\\wamp64\\www\\apitest\\vendor\\laravel\\framework\\src\\Illuminate\\Support\\Traits\\ForwardsCalls.php on line 23",
As I said it works with postman, but can't make this works from axios
Laravel controller:
public function store(Request $request) {
$offer = Offer::create($request->input('offer'));
$offer->category()->sync($request->input('category'));
$offer->save();
return response()->json($offer);
}
Boussadjra Brahim is right the issue is in the backend But its caused by sending null values from the frontend so we have to take a look at frontend.
first thing is using {} meaning u are creating object , [] is array and laravel create method accept array only
the input is an array itself as u are accessing it keys with (dot) so why not just set offer to the whole array and then separate them in the backend ? like this
axios.post('http://api.wip/api/offer/store', {
offer:this.input,
author_user_id: id,
category: 2
},
in your backend u can access them like :
$title = $request->offer['title'];
one last thing, when u are using create method the keys must be the same name as the column name in database or it will throw error!
hope it helps
I have tried a few different methods to get filtered data back from the REST API but cannot figure out the correct formatting for queries. This work for me:
var query = encodeURIComponent('where=' + '{"' + type + '":"' + subtype + '"}');
$http.get('https://api.parse.com/1/classes/events?' + query,
{headers:{
'X-Parse-Application-Id': PARSE_CREDENTIALS.APP_ID,
'X-Parse-REST-API-Key':PARSE_CREDENTIALS.REST_API_KEY,
'Content-Type' : 'application/json'
}
})
},
But when trying to include the additional parameters such as 'include', 'limit', and 'count' I have tried many iterations, but to no avail. Most queires returned a bad response, however this query returns an empty array (which isn't what I would like, but at least it returned something):
var query = encodeURIComponent('where=' + '{"' + type + '":"' + subtype + '", "limit":2}')
I have also tried using a params object with Angular's $http object but even with the same formatting as the above query, it returns a bad response. Can anyone give me the correct formatting for this as well? This, for example, does not seem to work:
$http.get('https://api.parse.com/1/classes/events',
{params: {"where" : encodeURIComponent('{"senses":"touch"}') }},
{headers:{
'X-Parse-Application-Id': PARSE_CREDENTIALS.APP_ID,
'X-Parse-REST-API-Key':PARSE_CREDENTIALS.REST_API_KEY,
'Content-Type' : 'application/json'
}
})
Thanks!
You are "overthinking" this since a lot of the problems with encoding are quite common and have the benefit of being already solved. So, you don't need to do string formatting/encoding with $http - just use objects.
Also, after checking parse.com API, limit, count and include are siblings of where - not children.
So, all you need to do is:
var whereQuery = {type: subtype};
$http.get('https://api.parse.com/1/classes/events',
{
headers: {
'X-Parse-Application-Id': PARSE_CREDENTIALS.APP_ID,
'X-Parse-REST-API-Key': PARSE_CREDENTIALS.REST_API_KEY,
'Content-Type' : 'application/json'
},
params: {
where: whereQuery,
limit: 2,
// count: 1
// include: "something"
}
});