Here is my angular 6 code
saveQuestion(value : string) : Observable<string> {
console.log(value)
let params = new HttpParams();
params = params.set('id', value);
return this._http.post<string>(this.subjectAPi + 'api/Question/Save/', {params});
}
below is my .net core code
[HttpPost("[action]")]
public IActionResult Save([FromBody]string id)
{
Question ob = new Question();
ob.update(id) // id is always null
return Ok("1");
}
ID is always null. Suggestion will be really appreciated
The HttpParams is for preparing URL encoded parameters, if you'd like to post a body in JSON you don't need that. Try just simply create your data like:
let body = { id: value }
this._http.post<string>(this.subjectAPi + 'api/Question/Save/', body);
If you really want to post your body as URL encoded data try to set the Content-Type request header:
this._http.post<string>(this.subjectAPi + 'api/Question/Save/', params.toString(), {
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
});
If I'm not mistaking, ASP.NET Core does not work with camelCasing for JSON by default. Try renaming the id in the HttpParams to be Id.
saveQuestion(value : string) : Observable<string> {
let params = new HttpParams();
params = params.set('Id', value);
return this._http.post<string>(this.subjectAPi + 'api/Question/Save/', {params});
}
Related
I'm sending a post request to my asp.net server from angular and i tried printing the values of my custom model class (SchoolModel) and it's all the values corrent inside angular. But when i try to get these values on asp.net it doesn't return anything from inside the object. Please help me if i'm missing something.
My angular code request
const headers = {'Content-Type': 'application/json', };
const body = { schoolData };
this.http.post<any>(this.baseUrl + "Api/CreateSchool", body, { headers }).subscribe(response => {
console.log(response);
}, error => console.error(error));
My ASP.NET code:
[HttpPost]
[Route("Api/CreateSchool")]
public bool CreateNewSchool(SchoolModel schoolData)
{
bool schoolCreated = false;
// IT PRINTS SCHOOL NAME ONLY
Console.WriteLine("SCHOOL NAME " + schoolData.Name);
return schoolCreated;
}
Use FromBody attribute.
public bool CreateNewSchool([FromBody]SchoolModel schoolData)
{
I had to use JSON.stringify(body) to make it work
I posted an XmlRequest with native JavaScript to my controller, but it doesn't accept the request body as a parameter. I.e. it reads it as a null even if the parameter is meant to be a string.
The request:
request.open("POST", "https://localhost:44328/CommodityTypes/PostData");
//request.setRequestHeader('Content-type', 'text'); // maybe that makes the problem?
request.send("Message");
The controller:
[HttpPost]
public string PostData(string Text)
{
return JsonSerializer.Serialize(Text);
}
Will be happy to get any advice on it.
After getting deeper into the business I found, that one can specify 'object' as
a parameter to parse for ('[FromBody]' attribute stays), getting a curious object, that gives the JSON message invoking ToString() method. If you have a variable or uneven structure of incoming JSON you may use this aproach.
Though there must be some other, meant way of handling the issue.
You can create object data = { "text": "YourText" } and send JSON.stringify(data)
And need set header xmlhttp.setRequestHeader('Content-Type', 'application/json');
var uri = '/CommodityTypes/PostData';
var xmlhttp;
xmlhttp = new XMLHttpRequest();
var data = { "text": "YourText" };
var sendstr = JSON.stringify(data);
xmlhttp.open("POST", uri, true);
xmlhttp.setRequestHeader('Content-Type', 'application/json');
xmlhttp.send(sendstr);
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200)
alert(xmlhttp.responseText);
}
in POST you have to send the Text parameter as FormData so it can be recognized and mapped by the method
var data = new FormData();
data.append("Text", "test");
var xhr = new XMLHttpRequest();
xhr.addEventListener("readystatechange", function() {
if(this.readyState === 4) {
console.log(this.responseText);
}
});
xhr.open("POST", "https://localhost:44328/CommodityTypes/PostData");
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.send(data);
I'm calling a POST controller action using fetch, but in the controller, the body appears to be null.
Here's my fetch code snippet - this is in a .net core Vue project. It's a typescript file.
var data = JSON.stringify(this.newProduct);
console.log(data)
fetch('api/Product/AddNewProduct', {
method: 'POST',
body: data,
headers: {
'Content-Type': 'application/json'
}
}).then(res => res.json())
.then(response => console.log('Success:', JSON.stringify(response)))
.catch(error => console.error('Error:', error));
And here's the request (and payload) as I can see it in Firefox:
But in my .net core backend, when the API gets hit, I can't seem to get the value of the body or anything in the request.
[HttpPost("[action]")]
public IActionResult AddNewProduct([FromBody] string body)
{
Product newProduct;
try
{
/*Added the below snippet for testing, not sure if actually necessary */
using (var reader = new StreamReader(Request.Body))
{
var requestBody = reader.ReadToEnd();
// Do something
}
//Convert the request body to an object
newProduct = JsonConvert.DeserializeObject<Product>(body);
}
catch (Exception e)
{
return new BadRequestResult();
}
Here, in my debugger, both body and requestBody are null. Any ideas?
.NET isn't seeing you passing a string, it sees a JSON because you pass the Content-Type header of application/json so it will try to deserialize it and map it to your request object. In your case, because your parameter is string body the parser tries to map the JSON object to your string and fails - so it passes null.
You can try and change the request to pass text/plain as the content-type (or remove the content-type header) or change your API parameter to the object you are sending:
public IActionResult AddNewProduct([FromBody] Product newProduct)
{
...
}
Add to headers Accept
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
},
I am trying to send data to my backend, but when it comes to backend it catches an expception thus returns error message.
I am assuming this is becuase data format from client side is somehow different than what I expected.
I expcect my backend to receive json string(I have other function that takes jsong string to object later).
What am I doing it wrong? I am aware that I can create modelling class for my data from client in my backend, but I need to work it without them and it shoud work as data are all string from my client
from client.
client
//to backend
callServer() {
var data = JSON.stringify(test);
//dispaly JSON like {"GradeA" : "23", "GradeB" : "45", "GradeC" : "22"}
console.log(data);
const headers = new HttpHeaders().set('Content-Type', 'application/json');
this.appService.http.post('http://localhost:2717/api/testAPi/test', data, {headers: headers})
.subscribe(data => {console.log(data), (err) => console.error("Failed! " + err);
})
}
backend
public class testAPiController : ApiController
{
private static readonly ILog Log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
public string test([FromBody] string body)
{
try
{
Log.Info(string.Format("data {0}", body));
//convert to json object
return json_object;
}
catch (Exception ex)
{
Log.Error(ex.Message);
return "error";
}
}
}
Config
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
// Web API configuration and services
log4net.Config.XmlConfigurator.Configure();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { action = "GET", id = RouteParameter.Optional }
);
}
}
Updated1
I don't get any error message, but return my body as null
Updated2
this.appService.http.post('http://localhost:2717/api/testAPi/test', "{\"GradeA\" : \"23\", \"GradeB\" : \"45\", \"GradeC\" : \"22\"}", {headers: headers})
still not working with different format of the body while Postman works with it
I am 99% sure it is caused by that you are defining that you are sending JSON (object) - your header shows that to WebAPI:
headers = new HttpHeaders().set('Content-Type', 'application/json');
and this object is quite complex.
In Controller you are expecting simple string.
You should either:
Move JSON deserializing job to Controller by defining model in method prototype:
public string test([FromBody] YourClassResemblingJson body)
{
...
}
Please look at more detiled information in this matter at: Post json data in body to web api
Or just send your JSON as properly formatted string. So JSON that originally looks like this:
{"body": "sampleBody"}
should look like this:
"{\"body\": \"sampleBody\"}"
Your code for this would look like this:
callServer() {
var data = JSON.stringify(test);
data = "\"" + data.replace("\"", "\\\"") + "\"";
//display JSON like "{\"GradeA\" : \"23\", \"GradeB\" : \"45\", \"GradeC\" : \"22\"}"
console.log(data);
const headers = new HttpHeaders().set('Content-Type', 'application/json');
this.appService.http.post('http://localhost:2717/api/testAPi/test', data, {headers: headers})
.subscribe(data => {console.log(data), (err) => console.error("Failed! " + err);
})
}
In first approach you'll have body object filled with your data from JSON, and in the second approach you'll have correct string in your body variable.
Sorry for so much editing, but I wasn't sure about what exactly is your problem, so it took me some time to dig up into the WebAPI specifications.
Very first your API method is GET method since that's default but from client you are making a POST call. Other than that, the passed data is not getting used anywhere
public string test([FromBody] string body)
{
Trying to Post a file and some data to MVC 5 backend.
Issue is it's not mapping properly so it's returning a 404. The Http post request is being sent over as a multipart/form-data content type.
Here is the Http post from angular service
requestInputHeat: function (qty, date, camp, note, file1) {
return $http({
method: 'POST',
url: '/log/heat/request',
headers: {
'Content-Type': 'multipart/form-data'
},
data: {
Quantity : qty,
RequestDate: date,
CampaignDetail: camp,
Notes: note,
File: file1
},
transformRequest: function (data, headersGetter) {
var formData = new FormData();
angular.forEach(data, function (value, key) {
formData.append(key, value);
});
var headers = headersGetter();
delete headers['Content-Type'];
return formData;
}
})
}
Here is the controller MVC5 backend I have trying to receive this request (using mvcmapping atrributes)
[HttpPost]
[Route("log/heat/request")]
public ActionResult RequestPOHeat(string Quantity, string RequestDate, string CampaignDetail, string Notes, HttpPostedFileBase File)
{
......
}
Please try following
In angularJs
function requestInputHeat(qty, date, camp, note, file1) {
var request = {
method: 'POST',
//public ActionResult RequestPOHeat(string Quantity, string RequestDate, string CampaignDetail, string Notes)
//your Controller Action RequestPOHeat requires 4 query strings which was previously not send in your code which I had passed below. This was giving 404 error.
url: '/log/heat/request?Quantity=' + qty.toString() + '&RequestDate=' + date.toString() + '&CampaignDetail=' + camp.toString() + '&Notes' + note.toString(),// I don't know the datatype so had converted them to string.Please change them to corresponding type once it's working. Also don't forget to map type with RequestPOHeat method parameter of controller.
data: { file: file1 },
headers: {
//IMPORTANT!!! You might think this should be set to 'multipart/form-data'
// but this is not true because when we are sending up files the request
// needs to include a 'boundary' parameter which identifies the boundary
// name between parts in this multi-part request and setting the Content-type
// manually will not set this boundary parameter. For whatever reason,
// setting the Content-type to 'false' will force the request to automatically
// populate the headers properly including the boundary parameter.
'Content-Type': undefined
},
transformRequest: function (data) {
var formData = new FormData();
angular.forEach(data, function (value, key) {
formData.append(key, value);
});
return formData;
},
};
return $http(request).success(function (result) {
return result.data;
}).error(function () {
});
}
In MVC Controller
[HttpPost]
[Route("log/heat/request")]
public ActionResult RequestPOHeat(string Quantity, string RequestDate, string CampaignDetail, string Notes)
{
var file = HttpContext.Current.Request.Files.Count > 0 ? HttpContext.Current.Request.Files(0) : null;
if (file != null && file.ContentLength > 0) {
//If file is posted you will get here..
}
......
}
Hint: What is bounty Parameter?
The boundary parameter is set to a number of hyphens plus a random string at the end, but you can set it to anything at all. The problem is, if the boundary string shows up in the request data, it will be treated as a boundary.