I'm having trouble getting a JSON response from a POST Request from my .Net Core server. In essence I would be using this POST request like a GET request from the server. I believe I'm passing in the correct headers, however, in my console error I'm getting
ERROR TypeError: Cannot read property 'sessionId' of undefined
I suspect it's something that has to do with the type and/or model. Or possibly how I'm calling it in the service. If I need to add anything for clarification, lmk.
.NET CORE Server Code
Action.Dto
{
public class ActionDto
{
public string SessionId { get; set; }
public Tag ActionTag { get; set; }
public ActionParams Args { get; set; }
}
}
ActionService.cs
{
ActionResponse LaunchAction(string sessionId, Tag actionTag, ActionParams args, UserState userState);
}
Action Controller
public IActionResult LaunchAction([FromBody]ActionDto launchActionParameters)
{
var sessionId = launchActionParameters.SessionId;
var actionTag = launchActionParameters.ActionTag;
var args = launchActionParameters.Args;
UserState userState = null;
RunAction runAction = null;
Angular Client Code
Action Component
export interface ActionView {
actionName: string;
actionType: string;
primaryTable: string;
specialUse: string;
folder: string;
actionDescription: string;
actionTag: number;
chartType: string;
priority: number;
}
const ACTION_DATA: ActionView[] = [];
#Component({
templateUrl: 'home.component.html'
})
export class HomeComponent implements OnInit, OnDestroy {
// User Fields
currentUser: User;
users: User[] = [];
currentUserSubscription: Subscription;
// Action Fields
currentAction: Action;
actions: Action[] = [];
displayedColumns: string[] =
['actionName', 'actionType', 'primaryTable', 'specialUse',
'folder', 'actionDescription', 'actionTag', 'chartType',
'priority'];
dataSource: any = new MatTableDataSource(ACTION_DATA);
constructor(
private authenticationService: AuthenticationService,
private iconRegistry: MatIconRegistry,
private sanitizer: DomSanitizer,
private httpClient: HttpClient,
private actionService: ActionService
) {
this.currentUserSubscription = this.authenticationService.currentUser.subscribe(user => {
this.currentUser = user;
});
this.iconRegistry.addSvgIcon(
'thumbs-up',
this.sanitizer.bypassSecurityTrustResourceUrl('assets/img/examples/thumbup-icon.svg'));
}
#ViewChild(MatSort) sort: MatSort;
public getActions() {
console.log('test');
this.actionService.getActions(
this.currentAction).subscribe((data) => {
this.dataSource = data;
});
}
ngOnInit() {
this.dataSource.sort = this.sort;
this.getActions();
}
ngOnDestroy() {
// unsubscribe to ensure no memory leaks
this.currentUserSubscription.unsubscribe();
}
}
Action Service
#Injectable({ providedIn: 'root' })
export class ActionService {
public apiURL = 'http://localhost:15217/api';
public currentUser: Observable<User>;
public currentAction: Observable<Action>;
constructor(private http: HttpClient) { }
// Http Options
httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json'
})
};
getActions(action: Action): Observable<Action[]> {
return this.http.post<Action[]>(this.apiURL + '/actions/launchactions',
{
sessionId: action.sessionId,
tag: action.actionTag,
actionParams: action.actionParams
})
.pipe(
retry(1),
catchError(this.handleError)
);
}
// Error handling
handleError(error: any) {
let errorMessage = '';
if (error.error instanceof ErrorEvent) {
// Get client-side error
errorMessage = error.error.message;
} else {
// Get server-side error
errorMessage = `Error Code: ${error.status}\nMessage: ${error.message}`;
}
window.alert(errorMessage);
return throwError(errorMessage);
}
add [FromBody] to controller side service, before the parameter. Post method pass parameters in body.
like
ActionResponse LaunchAction([FromBody]string sessionId, [FromBody]Tag actionTag, [FromBody]ActionParams args, [FromBody]UserState userState);
I don't know why microsoft did not decide to do this default.
You should remove {} from data: {}
By doing this you are assigning an empty object to that
What if you remove the "params" word from your angular http post call ?
So the http post call is this instead
return this.http.post<Action[]>(this.apiURL + '/actions/launchactions',
{
sessionId: action.sessionId,
tag: action.actionTag,
actionParams: action.actionParams
})
.pipe(
retry(1),
catchError(this.handleError)
);
Related
So I have my endpoint defined like the following:
[ApiController]
[Route("load/stuff")]
public class SignUp : ControllerBase
{
IGoogleRecaptchaV3Service _gService { get; set; }
public SignUp(IGoogleRecaptchaV3Service gService)
{
_gService = gService;
}
[HttpPost]
public async Task<IActionResult> Post([FromQuery] SignUpModel SignUpData, GRequestModel.Factory grequestFactory)
{
GRequestModel grm = grequestFactory("resValue", "remipValue");
_gService.InitializeRequest(grm);
if (!await _gService.Execute())
{
//return error codes string.
return Ok(_gService.Response.error_codes);
}
//call Business layer
return base.Content("Content here", "text/html");
}
}
This should return the HTML content if the reCAPTCHA score is human-like.
Let me know how to debug this further and whether any further code is required.
UPDATE fetch JS Code
function loadStuff() {
if (location.pathname === "/test") {
grecaptcha.execute('recaptchasitekeyhere', { action: 'onloadafterdelay' }).then(function (token) {
console.log(token);
return fetch("/load/stuff?RecaptchaToken=" + token, {
method: "POST",
body: token,
})
}).then((response) => {
// console.log works here too
if (!response.ok) {
const errorBuild = {
type: "Error",
message: response.message || "Something went wrong",
data: response.data || "",
code: response.code || "",
};
console.log("Error: " + JSON.stringify(errorBuild));
}
response.text().then(body => {
//console.log(body);
document.getElementById("test1").innerHTML = body.split(' ')[0];
document.getElementById("test2").innerHTML = body.split(' ')[1];
});
}
)
}
}
I also added this in the program.cs file:
builder.Services.AddControllers();
// FIX TEST
builder.Services.AddTransient<GRequestModel.Factory>(serviceProvider =>
(string res, string remip) => new GRequestModel(serviceProvider.GetRequiredService<IConfiguration>(), res, remip));
//Register dependencies
builder.Services.AddRazorPages();
// REMOVE ME IN PRODUCTION, USE DI INSTEAD
// ....
Configuration = app.Configuration;
// ...
public partial class Program
{
internal static IConfiguration Configuration { get; private set; }
}
I added that code above as a temporary fix, but then I tried to implement dependency injection for the IConfiguration and my codebase got dirty. I'm still a beginner in C# and I'm learning by trial and error hence so many mistakes.
I am trying to post data from angular 5 component to action method of .net core. I am able to hit the action method but values are null. As per below example Usr.FirstName is null in Sush action method.
Model-
namespace VModels
{
public class UserVM
{
public long UserId { get; set; }
public string FirstName { get; set; }
}
}
Action method of .net core-
[HttpPost]
public IActionResult Sush(UserVM Usr)
{
UserVM objOutput = new UserVM();
CommonGetPostMethod<UserVM, UserVM> objCommonMthd = new CommonGetPostMethod<UserVM, UserVM>();
UserVM objvm = new UserVM();
objvm.FirstName = "Susheel " + DateTime.Now.Ticks.ToString();
objCommonMthd.SaveData(Usr, "https://localhost:44303/api/UserAPI", ref objOutput);
return View(Usr);
}
Post method in angular 5-
SaveUser(userofrm: NgForm) {
var model = userofrm.value;
var values = JSON.stringify(model);
this.hpclient.post<UserVM>("https://localhost:44321/User/Users/Sush", values).subscribe(success => { }, fail => { });
}
Based on the code that you provided, I did a test with the following simple example, which work well on my side, you can refer to it.
// make request with testing data
var model = {'FirstName':'Test'};
var values = JSON.stringify(model);
console.log(values);
this.hpclient.post<UserVM>("https://localhost:44305/api/data/Sush", values, httpOptions).subscribe(success => { console.log(success);}, fail => { });
Define and configure headers for request(s)
import { HttpClient, HttpHeaders } from '#angular/common/http';
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json'
})
};
API controller action
[HttpPost("Sush")]
public IActionResult Sush(UserVM Usr)
{
Usr.UserId = 100;
return Ok(Usr);
}
Test Result
To troubleshoot the issue, you can try to make request with same data from postman etc tool and check if you can get expected data within action method. Or make request with testing data (as I did) rather than value inside userofrm, then check if it can work for you.
Here is my code for Method in TypeScript
Ive been trying to pass an number[] array to the controller to send to a quickbooks api but all i really need right now is to get the values into the controller,
This is been done in Angular 5 .net core 2.0 latest version
The data hits the Post Method with no error and i have breakpoints everywhere it never reaches the controller.
import { Injectable } from '#angular/core';
import { Customer } from '../models/customer';
import { Vendor } from '../models/vendor';
import { Item } from '../models/item';
import { Invoice } from '../models/invoice';
import { CreditNote } from '../models/creditNote';
import { PPO } from '../models/ppo';
import { PO } from '../models/po';
import { AppSettings } from '../models/appSettings';
import { Http, Response, Headers, RequestOptions, RequestMethod, URLSearchParams } from '#angular/http';
import { Observable } from 'rxjs/Observable';
import { MsgResult } from '../models/msgResult';
import { Router, ActivatedRoute } from '#angular/router';
import { isPlatformBrowser, isPlatformServer } from '#angular/common';
#Injectable()
export class SyncDataService {
errorMessage: string = "";
baseURL: string = 'http://localhost:56199/api';
constructor(private _http: Http, private route: ActivatedRoute, private router: Router) {}
syncCustomers(ids: Array<number>) {
var headers = new Headers();
headers.append('Content-Type', 'application/json; charset=utf-8');
var localStorage1 = localStorage.getItem('access_token');
if (localSt
orage1 != undefined) {
var token = JSON.parse(localStorage1);
//headers.append('Authorization', 'bearer ' + token);
//return this._http.post(this.baseURL + '/customer', ids, options)
// .map((response: Response) => <string>response.json())
// .catch(err => {
// return this.handleError(err);
// });
var stringids = JSON.stringify({ customerIDs: ids });
this._http.post(this.baseURL + '/customer/PostCust',
stringids).subscribe(result => result.json()), err => {
return this.handleError(err);
}
}
}
}
Here is my controller
[Route("api/[controller]")]
public class CustomerController : Controller
{
private readonly SyncDbContext _dbContext;
public CustomerController(SyncDbContext dbContext)
{
_dbContext = dbContext;
}
[HttpGet]
public List<Customer> Get()
{
return new SyncDataManager().GetCustomers();
}
[HttpPost("[action]")]
[AllowAnonymous]
public JsonResult PostCust([FromBody]int[] customerIDs)
{
// call quicbooks api and pass them the customers
// once quickbooks verifys the customer and sends us back a reference
// pass the quickbooks customer to SyncDataManager
var sync = new SyncDataManager();
var results = sync.UpdateCustomers(customerIDs);
var failedResults = results.Where(m => m.Success == false).ToList();
if(failedResults.Count == 0)
{
var json = new JsonResult("Updated Successfully");
json.StatusCode = 200;
return json;
}
else
{
var error = new StringBuilder();
foreach (var errorMessage in failedResults)
{
//string output = errorMessage.ErrorMessage.Substring(errorMessage.ErrorMessage.IndexOf('.') + 1);
string output = errorMessage.ErrorMessage;
error.AppendLine(output);
}
var json = new JsonResult(error.ToString());
json.StatusCode = 400;
return json;
}
}
There is no error messages and when i use break points on my controller, It does not hit the break points, been at it for 3 days no break through Please help
try in your Controller
[Route("api/[controller]/[action]")] //<--include action
public class CustomerController : Controller
{
...
[HttpGet,ActionName("Get")] //<--I don't know if it's necesary
public List<Customer> Get() {..}
[HttpPost, ActionName("PostCust")] //<--give there the "actionName
[AllowAnonymous]
public JsonResult PostCust([FromBody]int[] customerIDs){...}
}
this._http.post(this.baseURL + '/customer/PostCust',
this.customerIDs).subscribe((data:Response) => { this.resu = (data.json() as string) },
error => {
alert(error.json());
},
() => {
alert("Completed");
} else {
this.RefreshCustomers();
}
});
this.resu is my results variable
and no headers or casts for this.customerIDs this worked for me
I have an ASP.NET Core 2.0 Web API Integrated with ionic 3.
I'm having problems receiving JSON data sent from ionic 3 App, Here is sample code:-
import { Injectable } from '#angular/core';
import { Http, Headers } from '#angular/http';
import 'rxjs/add/operator/map';
import { AlertController, LoadingController } from 'ionic-angular';
import { FCM } from '#ionic-native/fcm';
#Injectable()
export class ServerProvider {
private baseurl = "http://localhost:9681/api";
private api: String[] = new Array();
public loader: any;
constructor(public fcm: FCM, public http: Http, public alertCtrl:
AlertController, public loadingCtrl: LoadingController) {
this.api['auth'] = 'Authentication';
this.api['agency'] = 'Agencies';
this.api['user'] = 'Users';
this.api['route'] = 'Routes';
this.api['token'] = 'Tokens';
this.api['notification'] = 'Notifications';
this.api['salepoint'] = 'Salepoints';
}
ServerRequest(api, request, data) {
return new Promise((resolve) => {
let headers = new Headers();
headers.append('Content-Type', 'application/json; charset=UTF-8');
this.http.get(this.baseurl + "/" + this.api[api] + "/", {headers: headers}).map(res => res.json()).subscribe((result) => {
resolve(result);
console.log(result);
}, (error) => {
console.log(error); this.CreateAlert("Error", error, [
{
text: 'Close',
handler: () => {
this.loader.dismiss();
}
}
]);
}, () => {
this.loader.dismiss();
});
});
}
Backend:-
[Route("api/Authentication")]
public class AuthenticationController : Controller
{
IConfiguration _configuration;
public AuthenticationController(IConfiguration configuration)
{
_configuration = configuration;
}
[HttpGet]
public JsonResult GetUser(JsonResult json)
{
AgencyUsers agencyusers = new AgencyUsers(_configuration);
return Json(agencyusers.GetUser(json));
}
}
I receive the following error:-
An unhandled exception occurred while processing the request.
InvalidOperationException: Could not create an instance of type
'Microsoft.AspNetCore.Mvc.JsonResult'. Model bound complex types must
not be abstract or value types and must have a parameterless
constructor.
What is the correct way to receive (serialize and deserialize JSON) and send back JSON (data or errors)?
After a lot of digging and modifications, I have finally got the API to work fine.
In case someone ran into a problem similar to mine, Here what I did:-
At Ionic, I have changed the HTTP request from GET to POST.
ServerRequest(api, request, data) {
return new Promise((resolve) => {
let headers = new Headers();
headers.append('Content-Type', 'application/json; charset=UTF-8');
this.http.post(this.baseurl + "/" + this.api[api] + "/" + request, JSON.stringify(data),{headers:headers}).map(res => res.json()).subscribe((result) => { ... });}
At Backend, Used newtonsoft (JObject) Which saved me a lot of head that JsonResult causes, Then Changed Method type to IActionResult.
[HttpPost("GetAgencyUser")]
public IActionResult GetAgencyUser([FromBody]JObject request)
{
try
{
if (request["id"] == null)
{
return Ok("id is not defined or incorrect JSON format");
}
AgencyUsersMethods agencyusers = new AgencyUsersMethods(_configuration);
var result = agencyusers.GetAgencyUser(request);
if (result == null)
{
return Ok("User not Found");
}
else
{
return Ok(result);
}
}
catch (Exception ex)
{
return BadRequest(ex.Message);
}
}
I am trying to write a login service (in typescript), which posts the username and password to my C# controller. The C# controller then makes a service call that hits my database to authenticate the user, but that is out of scope for this question.
The issue is that when I try to call my authentication function (which is found in my angular service) from my angular controller, I get an error in my console that it is unable to get property 'Authenticate' of undefined or null reference.
Here is the base class (Handler) for my services:
module app.Services {
export class HttpHandlerService {
httpService: ng.IHttpService;
handlerUrl: string;
constructor($http: ng.IHttpService) {
super();
this.httpService = $http;
}
useGetHandler(params: any): ng.IPromise<any> {
var result: ng.IPromise<any> = this.httpService.get(this.handlerUrl, params)
.then((response: any): ng.IPromise<any> => this.handlerResponded(response, params));
return result;
}
usePostHandler(params: any): ng.IPromise<any> {
var result: ng.IPromise<any> = this.httpService.post(this.handlerUrl, params)
.then((response: any): ng.IPromise<any> => this.handlerResponded(response, params));
return result;
}
handlerResponded(response: any, params: any): any {
response.data.requestParams = params;
return response.data;
}
}
}
Then my login service inherits it:
module app.Services {
export interface ILoginService {
Authenticate(email: string, password: string): ng.IPromise<any>;
}
export class LoginService extends Services.HttpHandlerService {
static $inject = ['$http'];
constructor($http: ng.IHttpService) {
this.handlerUrl = '/Login';
super($http);
}
// Authentication function I am attempting to call
Authenticate(email: string, password: string): ng.IPromise<any> {
// I have not completed the actual request that is being sent
var config: any = {};
var request = {
"Email": email,
"Password": password
}
return this.usePostHandler(config);
}
}
angular.module('App').factory('loginService', LoginService);
}
Here is my login controller where I'm calling the service:
module app.Login {
import Services = app.Services;
interface ILoginController {
email: string;
password: string;
login(): void;
}
class LoginController implements ILoginController{
email: string;
password: string;
loginService: Services.ILoginService;
loginForm: any;
static $inject = ["$state"];
constructor(private $state: ng.ui.IStateParamsService, loginService: Services.ILoginService) {
this.email = "";
this.password = "";
this.loginService = loginService;
}
login() {
if (this.loginForm.$invalid) {
return;
}
var request = this.loginService.Authenticate(this.email, this.password);
request.success(function (data) {
console.log("User authenticated.");
});
request.error(function () {
console.log("Error: User not authenticated.");
});
}
}
angular.module('App').controller('loginController', LoginController);
}
And finally my c# controller"
[HttpPost]
[Route("/Login")]
public async Task<IActionResult> Login()
{
// . . . .
}
Any help would be appreciated. Let me know if you need more information.
EDIT:
This is the javascript generated from the login service typescript:
var __extends = (this && this.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
var app;
(function (app) {
var Services;
(function (Services) {
var LoginService = (function (_super) {
__extends(LoginService, _super);
function LoginService($http) {
this.handlerUrl = '/Login';
_super.call(this, $http);
}
LoginService.prototype.Authenticate = function (email, password) {
var config = {};
var request = {
"Email": email,
"Password": password
};
return this.usePostHandler(config);
};
LoginService.$inject = ['$http'];
return LoginService;
})(Services.HttpHandlerService);
Services.LoginService = LoginService;
angular.module('App').factory('loginService', LoginService);
})(Services = app.Services || (app.Services = {}));
})(app || (app = {}));
I do get an error, only in IE, that _super is undefined.
Unable to get property 'Authenticate' of undefined or null reference. means that this.loginService was not properly injected by Angular.
You can try changing this:
static $inject = ["$state"];
to this:
static $inject = ["$state", "LoginService"];
Proper Dependency Injection in Your AngularJS TypeScript Apps