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.");
}
);
'''
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
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);
});
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 have an ASP.NET MVC app and I'm struggling with the connection between the typescript and the C#.
I can see that the C# is giving the response in the Inspect, the value is there but I don't know how to treat in Typescript.
C# Code:
namespace TEST.Controllers
{
[Route("api/[controller]")]
public class TestController : Controller
{
// GET api/GetTest
[HttpGet("GetTest")]
public IEnumerable<string> GetTest()
{
return new string[] { "Teste1", "Teste2" };
}
}
}
TypeScript SERVICE Code:
public getTest(): Observable<any> {
return this.dataService.get(this.baseUrl + '/GetTest')
.map((response: Response) => <any>response.json())
// .do(data => console.log("All: " + JSON.stringify(data)))
.catch(this.handleError);
}
Data Service Code (TypeScript):
public get<T>(url: string, params?: any): Observable<T> {
const options = new DataServiceOptions();
options.method = RequestMethod.Get;
options.url = url;
options.params = params;
return this.request(options);
}
private request(options: DataServiceOptions): Observable<any> {
options.method = (options.method || RequestMethod.Get);
options.url = (options.url || '');
options.headers = (options.headers || {});
options.params = (options.params || {});
options.data = (options.data || {});
this.interpolateUrl(options);
this.addXsrfToken(options);
this.addContentType(options);
this.addAuthToken(options);
// this.addCors(options);
const requestOptions = new RequestOptions();
requestOptions.method = options.method;
requestOptions.url = options.url;
requestOptions.headers = options.headers;
requestOptions.search = this.buildUrlSearchParams(options.params);
requestOptions.body = JSON.stringify(options.data);
this.pendingCommandsSubject.next(++this.pendingCommandCount);
const stream = this.http.request(options.url, requestOptions)
.catch((error: any) => {
this.handleErrors(error);
return Observable.throw(error);
})
.map(this.unwrapHttpValue)
.catch((error: any) => {
return Observable.throw(this.unwrapHttpError(error));
})
.finally(() => {
this.pendingCommandsSubject.next(--this.pendingCommandCount);
});
return stream;
}
The Calling:
private getDataBase() {
this.service.getTest().subscribe((res) => {
console.log(res);
this._proceduresImportData = res;
});
}
OBS: I also can console the observable, but I cannot treat it.
The best way to approach this is to have a generic request service and encapsulate your service calls, then inject that in where you need it. Taking get for an example (this can be expanded upon)
request.service.ts
import { Injectable } from "#angular/core";
import { Http, Response } from "#angular/http";
import { Observable } from "rxjs/Observable";
import "rxjs/add/operator/map";
import { WindowRef } from "./window.service";
#Injectable()
export class RequestService {
private baseUrl: string;
constructor(private http: Http, private windowRef: WindowRef) {
this.baseUrl = this.getBaseUrl();
}
public get<T>(resource: string): Observable<T> {
return this.http.get(this.baseUrl + resource)
.map<Response, T>(this.extractData);
}
private extractData(response: Response) {
return response.json();
}
private getBaseUrl(): string {
if (this.windowRef.getNativeWindow().location.hostname === "localhost") {
return "http://localhostAddress/api/";
} else if (this.windowRef.getNativeWindow().location.hostname === "anotherEnviroment") {
return "https://anotherAddress/api/";
}
}
}
window.service.ts
import { Injectable } from "#angular/core";
#Injectable()
export class WindowRef {
public getNativeWindow(): any {
return window;
}
}
This then returns an observable of the object you are expecting, used with a resolver or onInit it can be subscribed to where needed.
get-stuff.service.ts
import { Injectable } from "#angular/core";
import { Observable } from "rxjs/Observable";
import { RequestService } from "../common/request.service";
#Injectable()
export class Service {
constructor(private requestService: RequestService) { }
public getTestService(): void {
let requestedStuff: Observable<string[]> = this.requestService.get<string[]>(`GetTest`);
requestedStuff.subscribe(stuff: string[]) => {
//do stuff with your string
}
}
}
Then subscribe and use your data
Hope that helps
I am trying to load data from my web api controller.
Currently I am using my API service which I call from the ngOnInit function of the component.
But, nothing return in the view because it's an asynchronous data
Web api controller
[HttpGet("[action]")]
public async Task<UserModel> GetUserById(int id)
{
Response.StatusCode = 200;
try
{
_context = new AuthentificationDbContext();
UserModel user = await _context.User.SingleOrDefaultAsync(m => m.id == id);
if (user == null)
{
return null;
}
else
return (user);
}
catch (SqlException ex)
{
throw ex;
}
}
userService.ts
getUserId(id: number) : Observable<User>{
return this.http.get(this.url + 'userApi/GetUserById/?id=' + id)
.map(res => <User>res.json())
.catch(this.handleError);
}
app.routing.ts
{ path: 'user/:id', component: UserComponent}
export const routing = RouterModule.forRoot(appRoutes,{
enableTracing:true});
export const routedComponents = [UserComponent];
user.component.ts
export class UserComponent implements OnInit {
private user: User;
constructor(private userService: UserService, private route: ActivatedRoute, private router: Router) { }
ngOnInit() {
this.route.paramMap
.switchMap((params: ParamMap) =>
this.userService.getUserId(+params.get('id')))
.subscribe((user: User) => {
this.user = user;
});
}
}
user.cshtml
<div *ngIf="user">{{ user.name}}</div>
But, when I tried with that example, that's work because not asynchronous
import { Injectable, Inject } from '#angular/core';
import { Http, Response, RequestOptions, Headers } from '#angular/http';
import { Observable } from 'rxjs/Observable';
export class User {
constructor(public id: number, public name: string) { }
}
let Users = [
new User(11, 'Mr. Nice'),
new User(12, 'Narco')
];
let usersPromise = Promise.resolve(Users);
#Injectable()
export class UserService {
constructor( #Inject(Http) public http: Http) { }
getUserId(id: number | string) {
return usersPromise
.then(users => users.find(user => user.id === +id));
}
}
My question : how to load async data in ngOnInit?
I used by promise also, but doesn't work
If you use
{{user.view}}
in the components template, you'll get an error, because user isn't available immediately.
{{user?.view}}
(safe-nativation operator) avoids this error by not throwing an exception when user is null.
I can resolve my problem (it's related to routing) :
my code just need to insert this :
<script>document.write('<base href="' + document.location + '" />');</script>
at the top of the 'head' section.
And to insert in constructor from app.component.ts, this methode:
click() {
this.router.navigate(['', { foo: 'bar' }]);
}