My Angular (front-end) is making a POST request with JSON body and sends it to the server as follows :
const reponse = {
"Id_Harry" : this.harry.getId,
"x_harry" : this.harry.getX(),
"y_harry" : this.harry.getY(),
"Pv_Harry" : this.harry.getPv(),
"Force_Harry" : this.harry.getForce()
};
fetch(url, {
method: 'POST',
body: JSON.stringify(reponse),
headers :{
"Content-Type" : "application/json ,charset=UTF-8"
}
}).then((resp) => resp.json()).then(function(response) {
console.info('fetch()', response);
return response;
});
The back-end doesn't seem to recognize the server json body.The back-end code is a post that updates all the database with the values given by the json body.
The backend code is :
[Route("api/Harry/update")]
[HttpPost]
public IHttpActionResult PostHarry([FromBody] HarryViewModel harry)
{
try
{
if (harry == null)
{
return NotFound();
}
HarryDTO ha = new HarryDTO();
ha.Id_Harry = harry.Id_Harry;
ha.Pv_Harry = harry.Pv_Harry;
ha.Force_Harry = harry.Force_Harry;
ha.x_harry = harry.x_harry;
ha.y_harry = harry.y_harry;
_harryService.UpdateHarry(ha);
return Content(HttpStatusCode.OK,"OK");
}
catch (Exception ex)
{
return Content(HttpStatusCode.InternalServerError, "Something happenes!");
}
}
HarryViewModel class is :
public class HarryViewModel
{
public int Id_Harry { get; set; }
public int Pv_Harry { get; set; }
public int Force_Harry { get; set; }
public int x_harry { get; set; }
public int y_harry { get; set; }
}
The back-end doesn't seem to recognize the Angular json format. I get this error :
415 Unsupported Media Type. "no mediatypeformatter is available to read an object of type 'harryviewmodel' from content with media type 'application/octet-stream'."
Take a better look at the ERROR :
Thank you so much for your attention.
You are not passing response to the api.
const reponse = {
"Id_Harry" : this.harry.getId,
"x_harry" : this.harry.getX(),
"y_harry" : this.harry.getY(),
"Pv_Harry" : this.harry.getPv(),
"Force_Harry" : this.harry.getForce()
};
// Instead of this.checkResponse, pass "response" which is your post data.**
this.http.post(url, response).toPromise().then((data:any) => {
console.log(data);
console.log(data.json.test);
this.json = JSON.stringify(data.json);
});
And if API is not recognizing post data type, then pass on proper content type header to your post request like this:-
const reponse = {
"Id_Harry" : this.harry.getId,
"x_harry" : this.harry.getX(),
"y_harry" : this.harry.getY(),
"Pv_Harry" : this.harry.getPv(),
"Force_Harry" : this.harry.getForce()
};
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json'
})
};
this.http.post(url, response, httpOptions).toPromise().then((data:any) => {
console.log(data);
console.log(data.json.test);
this.json = JSON.stringify(data.json);
});
You can read more about HttpClient options here
I have checked your code:
Here's what you need to do :
import { HttpHeaders } from '#angular/common/http';
const response = {
"Id_Harry" : this.harry.getId,
"x_harry" : this.harry.getX(),
"y_harry" : this.harry.getY(),
"Pv_Harry" : this.harry.getPv(),
"Force_Harry" : this.harry.getForce()
};
const headers = new HttpHeaders();
headers.append('Content-Type', 'application/json');
headers.append('Accept', 'application/json');
this.http.post(url, response, { headers: headers }).toPromise().then((data:any) => {
console.log(data);
console.log(data.json.test);
this.json = JSON.stringify(data.json);
});
Related
I am passing the object from component to controller using angular and .NET but controller receiving ValueKind=Object I have tried to serialize and deserialize method too.
Angular Component code:
import { Component, Inject } from '#angular/core';
import { HttpClient } from '#angular/common/http';
#Component({
selector: 'login',
templateUrl: './login.component.html',
})
export class LoginComponent {
email: string;
password: string;
public http: HttpClient;
public baseUrl: string;
constructor(private _httpService: HttpClient, #Inject('BASE_URL') baseUrl: string)
{
this.http = _httpService;
this.baseUrl = baseUrl;
}
public loginUser()
{
let data: any = {} as any;
//console.log("Hello Login");
//console.log(this.email);
//console.log(this.password);
data.userEmail = this.email;
data.userPassword = this.password;
//JSON.stringify(this.data);
debugger;
this.http.post(this.baseUrl + 'api/Login/GetUserLogin', data).subscribe(result => {
console.log('my result is ='+result);
var l_arrResponse = result as any; //.json()
console.log(l_arrResponse);
}, error => console.error(error));
}
}
.NET Controller code:
namespace DataFetchingFromControllerApp.Controllers
{
[Route("api/[controller]")]
public class LoginController
{
[HttpPost("[action]")]
public IEnumerable GetUserLogin([FromBody]dynamic p_oPostData)
{
//var test=JsonConvert.DeserializeObject(p_oPostData);
string enteredUserEmail = p_oPostData.userEmail;
string enteredUserPassword = p_oPostData.userPassword;
return new string[] { "value1", "value2" };
}
}
}
In controller, p_oPostData containsValueKind=object by itself and below when i use p_oPostData.userEmail it gives exception.
try
p_oPostData.UserEmail //(the "U" uppercase)
Anyway, I would prefer declare a class RequestLogin with two properties and declare p_oPostData as RequestLogin, not as dynamic.
public class RequestLogin
{
public string UserEmail {get;set;}
public string UserPassword {get;set;}
}
//in your controller
public IEnumerable GetUserLogin([FromBody]RequestLogin p_oPostData){...}
NOTE: Forget headers.set('Content-type..) it's a error
I have an object class and i want to use it in my ASP.NET Core angular project. I can't map the object return through the http get method. Any options please?
class file:
[Serializable]
public class PricesRules
{
public HashSet<Price> Prices { get; set; }
public HashSet<Customer> Customers { get; set; }
public HashSet<Payment> Payments { get; set; }
}
component.ts :
public prices: PricesRules;
constructor(private http: HttpClient, #Inject('BASE_URL') private baseUrl: string) {
http.get<PricesRules>(baseUrl + 'api/UpdatePrices/GetLastPrices').subscribe(result => {
this.prices = result[0];
}, error => console.error(error));
}
interface PricesRules {
Prices: any[];
Customers: any[];
Payments: any[];
}
Controller file:
[HttpGet("[action]")]
public IEnumerable<PricesRules> GetLastPrices()
{
PricesRules pricesRules = null;
//some code here
yield return pricesRules;
}
In my component I have good values in my result object, but my object prices is undefined after.
Edit : Now the get method is ok, but my post method not firing my controller.
component.ts
'''
onClickSubmit(data) {
const params = new HttpParams().set('ID', '1');
const headers = new HttpHeaders().set('content-type', 'application/json');
this.http.post<PricesRules>(this.baseUrl + 'api/UpdatePrices/PostUpdatePrices' + this.prices, { headers, params }).subscribe(result => {
console.log("success");
}, error => console.error(error));
}
'''
Controller
'''
[HttpPost("[action]")]
public async Task<IActionResult> PostUpdatePrices([FromBody] PricesRules pricesRules)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
return null;
}
'''
I have this error :
Object { headers: {…}, status: 404, statusText: "Not Found", url: "https://localhost:44374/api/UpdatePrices/PostUpdatePrices[object%20Object]", ok: false, name: "HttpErrorResponse", message: "Http failure response for https://localhost:44374/api/UpdatePrices/PostUpdatePrices[object%20Object]: 404 Not Found", error: "\n\n\n\nError\n\n\nCannot POST /api/UpdatePrices/PostUpdatePrices%5Bobject%20Object%5D\n\n\n" }
I assume your api return PricesRules instead of IEnumerable<PricesRules>(as you said you get the data).So Because result will be an object like {Prices:[...],...} so you can not access it by index you will need to change
this.prices = result[0];
to
this.prices = result.Prices;
or this.prices = result['Prices'];
I have modify the component.ts
'''
const headers = new HttpHeaders()
.set("Content-Type", "application/json");
this.http.post(this.baseUrl + 'api/UpdatePrices/PostUpdatePrices',
this.prices,
{ headers })
.subscribe(
val => {
console.log("PUT call successful value returned in body",
val);
},
response => {
console.log("PUT call in error", response);
},
() => {
console.log("The PUT observable is now completed.");
}
);
'''
I have an ASP.NET MVC Controller defined like so:
[HttpPost]
public string uploadQAImage(FileUploadClass fileUploadClass, HttpPostedFile image)
{
}
And this what the class FileUploadClass looks like.
public class FileUploadClass
{
public string job { get; set; }
public string createdBy { get; set; }
public string itemId { get; set; }
}
What I am trying to do with Alamofire in iOS is call this Controller, I have tried using parameters:
func saveQAPhotos(_ cellHolder: PhotoClass, completion: #escaping (_ result: Dictionary<String, Any>) -> Void)
{
let parameters: Parameters = [
"job" : cellHolder.job!,
"itemId" : cellHolder.itemId!,
"createdBy" : appDelegate.username!
]
let urlComponents = NSURLComponents(string: webservice + "uploadQAImage");
urlComponents?.user = appDelegate.username;
urlComponents?.password = appDelegate.password;
let url = urlComponents?.url;
Alamofire.upload(multipartFormData: { (multipartFormData) in
for (key, value) in parameters {
multipartFormData.append("\(value)".data(using: String.Encoding.utf8)!, withName: key as String)
}
if let data = cellHolder.photo {
multipartFormData.append(data, withName: "image", fileName: "image.png", mimeType: "image/png")
}
}, usingThreshold: UInt64.init(), to: url!, method: .post, headers: nil) { (result) in
switch result{
case .success(let upload, _, _):
upload.responseJSON { response in
if let result = response.result.value {
let jsonData = result as! Dictionary<String, Any>
completion(jsonData)
}
}
case .failure(_):
print("error")
}
}
}
But that didn't work on the ASP.NET side I get this error:
can't bind multiple parameters to the request's content
I have also tried sending the data as [AnyHashable: Any] like so:
func saveQAPhotos(_ cellHolder: PhotoClass, completion: #escaping (_ result: Dictionary<String, Any>) -> Void)
{
var jsonDict = [AnyHashable: Any]()
jsonDict["job"] = cellHolder.job
jsonDict["itemId"] = cellHolder.itemId
jsonDict["createdBy"] = appDelegate.username
let jsonData: Data? = try? JSONSerialization.data(withJSONObject: jsonDict, options: .prettyPrinted)
let urlComponents = NSURLComponents(string: webservice + "uploadQAImage");
urlComponents?.user = appDelegate.username;
urlComponents?.password = appDelegate.password;
let url = urlComponents?.url;
Alamofire.upload(multipartFormData: { (multipartFormData) in
multipartFormData.append(jsonData!, withName: "fileUploadClass", mimeType: "application/json")
if let data = cellHolder.photo {
multipartFormData.append(data, withName: "image", fileName: "image.png", mimeType: "image/png")
}
}, usingThreshold: UInt64.init(), to: url!, method: .post, headers: nil) { (result) in
switch result{
case .success(let upload, _, _):
upload.responseJSON { response in
if let result = response.result.value {
let jsonData = result as! Dictionary<String, Any>
completion(jsonData)
}
}
case .failure(_):
print("error")
}
}
}
Same error as before
can't bind multiple parameters to the request's content
Now when I change the ASP.NET Controller to only get FileUploadClass like so:
[HttpPost]
public string uploadQAImage(FileUploadClass fileUploadClass)
{
}
I get this error:
Object reference not set to an instance of an object.
I can only assume if I do fix the can't bind multiple parameters to the request's content error I will get this error next.
I am pretty sure I am sending the data incorrectly, so I guess my question is how do I send data from Alamofire upload method to an ASP.NET MVC method?
I am working with angular 6 trying to send a post request using httpclient , but always receive null body on the server side.
save( rules:RuleModel[]){
let _headers: HttpHeaders = new HttpHeaders({
'Content-Type': 'application/json; charset=utf-8'
});
return this._httpClient.post(AppConfig.BaseUrl,JSON.stringify(rules), {headers:_headers} ); }
and API function
[HttpPost]
public List<Rule> AddTemplateTextRules( [FromBody]Rule[] Rules)
{
try
{
return RuleManager.AddRule(Rules);
}
catch (Exception e)
{
return null;
}
return null;
}
To make a post request in Angular 6 with standard practice you need to do followings:
In the service class:
import {throwError, Observable } from 'rxjs';
import {catchError} from 'rxjs/operators';
import { Injectable } from '#angular/core';
import { HttpClient, HttpHeaders, HttpParams, HttpErrorResponse } from '#angular/common/http';
import { Rule } from 'path';
#Injectable()
export class RuleService {
constructor(private httpClient: HttpClient) { }
private baseUrl = window.location.origin + '/api/Rule/';
createTemplateTextRules(rules: Rules[]): Observable<boolean> {
const body = JSON.stringify(rules);
const headerOptions = new HttpHeaders({ 'Content-Type': 'application/json' });
return this.httpClient.post<boolean>(this.baseUrl + 'AddTemplateTextRules', body, {
headers: headerOptions
}).pipe(catchError(this.handleError.bind(this));
}
handleError(errorResponse: HttpErrorResponse) {
if (errorResponse.error instanceof ErrorEvent) {
console.error('Client Side Error :', errorResponse.error.message);
} else {
console.error('Server Side Error :', errorResponse);
}
// return an observable with a meaningful error message to the end user
return throwError('There is a problem with the service.We are notified &
working on it.Please try again later.');
}
}
In the Component:
export class RuleComponent implements OnInit {
constructor(private ruleService: RuleService) { }
createTemplateTextRules(): void {
this.ruleService.createTemplateTextRules(rules).subscribe((creationStatus) => {
// Do necessary staff with creation status
}, (error) => {
// Handle the error here
});
}
}
Then in the ASP.NET Core API Controller:
[Produces("application/json")]
[Route("api/Rule/[action]")]
public class RuleController : Controller
{
[HttpPost]
public Task<IActionResult> AddTemplateTextRules( [FromBody]Rule[] Rules)
{
try
{
return RuleManager.AddRule(Rules);
}
catch (Exception e)
{
return false;
}
return Json(true);
}
}
Hope it will help you.
With the latest RxJS(Angular 14) here is the way:
Service
Login(phone:string,password:string)
{
let _headers: HttpHeaders = new HttpHeaders({
'accept': 'application/json'
});
return this.http.post(this.url,{username,password},{headers:_headers})
.pipe(map(response=>response));
}
Component
async Login(phone:string,password:string)
{
let token$ = this.authService.Login(phone,password);
let token = await lastValueFrom(token$);
}
Since I was returning just text and not Json from the API, this was my code to handle text response type in the Service. If you're getting a response parse error, explicitly defining the responseType will help since Json is default.
Login(phone:string,password:string)
{
let _headers: HttpHeaders = new HttpHeaders({
'accept': 'text/plain'
});
return this.http.post(this.url+'security/login?phone='+phone+'&password='+password,null,{headers:_headers,responseType:'text'})
.pipe(map(response=>response));
}
I am doing a http put method to the server sending an object with a list of PupilsScores.
The TestId is bound, but the PupilsScores collection is null.
I also tried [FromBody] but that should be the default I assume doing a post/put.
So why is my PupilsScores collection null?
CLIENT
updateTestAssignment(pupilsScores, testId) {
return this.http.put('/api/testassignments/' + testId, { pupilsScores: pupilsScores }).map(res => res.json());
}
SERVER
public class UpdateTestAssignmentRequestDto
{
public int TestId { get; set; }
public IEnumerable<PupilsScoresRequestDto> PupilsScores { get; set; }
}
[HttpPut("~/api/testassignments/{testId:int}")]
public async Task<IActionResult> Put(UpdateTestAssignmentRequestDto dto)
{
return NoContent();
}
You need to specify the Content-Type too. Its default value is text/plain.
import { Headers, RequestOptions } from '#angular/http';
let headers = new Headers({ 'Content-Type': 'application/json' }); // for ASP.NET MVC
let options = new RequestOptions({ headers: headers });
this.http.post(url, JSON.stringify(product), options).map(....)