NSwag Angular 5 how to get the json response? - json

I'm accessing an api and I generated using NSwagStudio a type script version of the api calls to use as services. I get the response from the server and seems to work fine, but I don't know how to access the json file with the response. I tried subscribing to the method that I'm calling but I always get null as a response. Any help or guidelines will be appreciated it.
Here is an example of the code generated by NSwagStudio and my implementation to subscribe to the response.
apiSubmissionGetResultMessageGet(...) {
protected processApiSubmissionGetResultMessageGet(response: HttpResponseBase): Observable<void> {
const status = response.status;
const responseBlob =
response instanceof HttpResponse ? response.body :
(<any>response).error instanceof Blob ? (<any>response).error : undefined;
let _headers: any = {}; if (response.headers) { for (let key of response.headers.keys()) { _headers[key] = response.headers.get(key); }};
if (status === 200) {
return blobToText(responseBlob).flatMap(_responseText => {
return Observable.of<void>(<any>null);
});
} else if (status !== 200 && status !== 204) {
return blobToText(responseBlob).flatMap(_responseText => {
return throwException("An unexpected server error occurred.", status, _responseText, _headers);
});
}
return Observable.of<void>(<any>null);
}
}
And this is where I'm trying to subscribe:
getSubmissionDetails(string): void {
this.client.apiSubmissionGetSubmissionDocumentGet('documentId')
.subscribe(
data => {
this.submissionList = this.submissionList;
console.log('data: ', data);
},
(error: any) => this.errorMessage = <any> error);
}

The return type is Observable<void> which means that it doesnt return anything...
Check that the operation has a response type in the swagger spec and regenerate.

Related

Uncaught SyntaxError: Unexpected number in kendo ui

I have kendo ui popup which sends a request to an action method. The action method returns json and then my code breaks in the kendo.all.min.js file and the error method says Uncaught SyntaxError: Unexpected number
My kendo code below:-
var cloudStore = new kendo.data.DataSource({
//batch: true,
pageSize: 25,
transport: {
create: {
url: "/Admin/AddCloudStore", //(/ControllerName/ActionName)
type: "POST"
},
update: {
url: "/Admin/UpdateCloudStore",
type: "POST"
},
parameterMap: function (data, operation) {
console.table(data);
var result = {};
// For update and create send the entire object
if (operation === "update" || operation === "create") {
return data;
//return JSON.stringify({ service: data });
}
return null;
}
},
schema: {
model: cloudStoreModel,
errors: "error"
},
error: function (e) {
console.log(e);
}
});
Am I suppose to return something else from the action? Any help on the issue would be appreciated
Edit: Okay seems like the problem is with what I am return from my .net action method. Adding my action method below:-
public ActionResult AddCloudStore(DataAccess.Model.domain_config_cloud store)
{
try
{
using (var context = new DataAccess.Model.CondadoMediaVault())
{
if (store.cld_cmp_key <= 0) store.cld_cmp_key = Session["sel_domain_key"].ConvertToLong();
var list = context.domain_config_cloud.Where(x => x.cld_cmp_key == store.cld_cmp_key && x.cld_is_active && x.cld_category == "primary").ToList();
if (list.Count > 0)
return Json("There is already a primary cloud store."); //returning string
long user_key = 0;
long.TryParse(Convert.ToString(Session["user"]), out user_key);
var maxKey = context.domain_config_cloud.OrderByDescending(x => x.cld_key).FirstOrDefault();
if (maxKey == null || maxKey.cld_key == 0)
return Json("Error"); //returning string
else
store.cld_key = maxKey.cld_key + 1;
context.domain_config_cloud.Add(store);
context.SaveChanges();
}
}
catch (Exception ex)
{
MediaVault.BLL.ErrorLoggging.DbExceptionLog.LogError(ex);
}
return Json(store); //returning object
}
So the kendo ui code breaks when a string is returned from the action method. If an object is returned the code does not break. What is the exact return type which is expected by kendo ui?

Google Data Studio Community Connector getData() not working as expected

function getData(request){
try{
var options = {
'method' : 'post',
'contentType': 'application/json',
'payload' : JSON.stringify(request)
};
response=UrlFetchApp.fetch(getDataUrl, options);
resData = JSON.parse(response.getContentText())
return resData
}catch (e) {
e = (typeof e === 'string') ? new Error(e) : e;
Logger.log("Catch", e);
throw e;
}
}
The the above is my getData() function.
My isAdminUser() returns true.
When I try to visualize my data, I get the following error
Data Set Configuration Error
Data Studio cannot connect to your data set.
There was an error requesting data from the community connector. Please report the issue to the provider of this community connector if this issue persists.
Error ID: 3d11b88b
https://i.stack.imgur.com/x3Hki.png
The error code changes every time I refresh data and I can't find any dictionary to map the error id to an error
I tried debugging by logging the request parameter, response.getContentText() and resData variable to make sure I my data is formatted correctly.
Following are the logs printed in Stackdriver logs
request
{configParams={/Personal config data/}, fields=[{name=LASTNAME}]}
response.getContentText()
{"schema":[{"name":"LASTNAME","dataType":"STRING"}],"rows":[{"values":["test"]},{"values":["test"]},{"values":["Dummy"]},{"values":["One"]},{"values":["Nagargoje"]},{"values":[""]},{"values":[""]},{"values":[""]},{"values":[""]},{"values":[""]}],"filtersApplied":false}
resData
{rows=[{values=[test]}, {values=[test]}, {values=[Dummy]},
{values=[One]}, {values=[Nagargoje]}, {values=[]}, {values=[]},
{values=[]}, {values=[]}, {values=[]}], filtersApplied=false,
schema=[{name=LASTNAME, dataType=STRING}]}
I am not sure what is wrong with my getData() function.
The Object that I am returning seems to match the structure given here https://developers.google.com/datastudio/connector/reference#getdata
So there was no issue with my getData() function, the issue existed in the manifest file.
I was searching about passing parameter via URL and I stumbled upon a field called
dataStudio.useQueryConfig and added that to my manifest file and set its value to true.
Google Data studio was expecting me to return a query Config for getData().
But what I really wanted was this.
Anyways, I was able to debug it thanks to Matthias for suggesting me to take a look at Open-Source implementations
I implemented JSON connect which worked fine, so I Logged what it was returning in getData() and used that format/structure in my code, but my connector still didn't work.
My next assumption was maybe there is something wrong with my getSchema() return value. So I logged that as well and then copy pasted the hard coded value of both getData() and getSchema() return varaibles from JSON connect.
And even that didn't work, so my last bet was there must be something wrong with the manifest file, maybe the dummy links I added in it must be the issue. Then, after carrying out field by comparison I was finally able to get my community connector working.
This would have been easier to debug if the error messages were a bit helpful and didn't seem so generic.
First: You can always check out the Open-Source implementations that others did for custom Google Data Studio connectors. They are a great source if information. Fore more information checkout the documentation on Open Source Community Connectors.
Second: My implementation is for a time tracking system thus having confidential GDPR relevant data. That's why I can not just give you response messages. But I assembled this code. It contains authentifiction, HTTP GET data fetch and data conversions. Explanation is below the code. Again, checkout the open-source connectors if you need further assistance.
var cc = DataStudioApp.createCommunityConnector();
const URL_DATA = 'https://www.myverysecretdomain.com/api';
const URL_PING = 'https://www.myverysecretdomain.com/ping';
const AUTH_USER = 'auth.user'
const AUTH_KEY = 'auth.key';
const JSON_TAG = 'user';
String.prototype.format = function() {
// https://coderwall.com/p/flonoa/simple-string-format-in-javascript
a = this;
for (k in arguments) {
a = a.replace("{" + k + "}", arguments[k])
}
return a
}
function httpGet(user, token, url, params) {
try {
// this depends on the URL you are connecting to
var headers = {
'ApiUser': user,
'ApiToken': token,
'User-Agent': 'my super freaky Google Data Studio connector'
};
var options = {
headers: headers
};
if (params && Object.keys(params).length > 0) {
var params_ = [];
for (const [key, value] of Object.entries(params)) {
var value_ = value;
if (Array.isArray(value))
value_ = value.join(',');
params_.push('{0}={1}'.format(key, encodeURIComponent(value_)))
}
var query = params_.join('&');
url = '{0}?{1}'.format(url, query);
}
var response = UrlFetchApp.fetch(url, options);
return {
code: response.getResponseCode(),
json: JSON.parse(response.getContentText())
}
} catch (e) {
throwConnectorError(e);
}
}
function getCredentials() {
var userProperties = PropertiesService.getUserProperties();
return {
username: userProperties.getProperty(AUTH_USER),
token: userProperties.getProperty(AUTH_KEY)
}
}
function validateCredentials(user, token) {
if (!user || !token)
return false;
var response = httpGet(user, token, URL_PING);
if (response.code == 200)
console.log('API key for the user %s successfully validated', user);
else
console.error('API key for the user %s is invalid. Code: %s', user, response.code);
return response;
}
function getAuthType() {
var cc = DataStudioApp.createCommunityConnector();
return cc.newAuthTypeResponse()
.setAuthType(cc.AuthType.USER_TOKEN)
.setHelpUrl('https://www.myverysecretdomain.com/index.html#authentication')
.build();
}
function resetAuth() {
var userProperties = PropertiesService.getUserProperties();
userProperties.deleteProperty(AUTH_USER);
userProperties.deleteProperty(AUTH_KEY);
console.info('Credentials have been reset.');
}
function isAuthValid() {
var credentials = getCredentials()
if (credentials == null) {
console.info('No credentials found.');
return false;
}
var response = validateCredentials(credentials.username, credentials.token);
return (response != null && response.code == 200);
}
function setCredentials(request) {
var credentials = request.userToken;
var response = validateCredentials(credentials.username, credentials.token);
if (response == null || response.code != 200) return { errorCode: 'INVALID_CREDENTIALS' };
var userProperties = PropertiesService.getUserProperties();
userProperties.setProperty(AUTH_USER, credentials.username);
userProperties.setProperty(AUTH_KEY, credentials.token);
console.info('Credentials have been stored');
return {
errorCode: 'NONE'
};
}
function throwConnectorError(text) {
DataStudioApp.createCommunityConnector()
.newUserError()
.setDebugText(text)
.setText(text)
.throwException();
}
function getConfig(request) {
// ToDo: handle request.languageCode for different languages being displayed
console.log(request)
var params = request.configParams;
var config = cc.getConfig();
// ToDo: add your config if necessary
config.setDateRangeRequired(true);
return config.build();
}
function getDimensions() {
var types = cc.FieldType;
return [
{
id:'id',
name:'ID',
type:types.NUMBER
},
{
id:'name',
name:'Name',
isDefault:true,
type:types.TEXT
},
{
id:'email',
name:'Email',
type:types.TEXT
}
];
}
function getMetrics() {
return [];
}
function getFields(request) {
Logger.log(request)
var fields = cc.getFields();
var dimensions = this.getDimensions();
var metrics = this.getMetrics();
dimensions.forEach(dimension => fields.newDimension().setId(dimension.id).setName(dimension.name).setType(dimension.type));
metrics.forEach(metric => fields.newMetric().setId(metric.id).setName(metric.name).setType(metric.type).setAggregation(metric.aggregations));
var defaultDimension = dimensions.find(field => field.hasOwnProperty('isDefault') && field.isDefault == true);
var defaultMetric = metrics.find(field => field.hasOwnProperty('isDefault') && field.isDefault == true);
if (defaultDimension)
fields.setDefaultDimension(defaultDimension.id);
if (defaultMetric)
fields.setDefaultMetric(defaultMetric.id);
return fields;
}
function getSchema(request) {
var fields = getFields(request).build();
return { schema: fields };
}
function convertValue(value, id) {
// ToDo: add special conversion if necessary
switch(id) {
default:
// value will be converted automatically
return value[id];
}
}
function entriesToDicts(schema, data, converter, tag) {
return data.map(function(element) {
var entry = element[tag];
var row = {};
schema.forEach(function(field) {
// field has same name in connector and original data source
var id = field.id;
var value = converter(entry, id);
// use UI field ID
row[field.id] = value;
});
return row;
});
}
function dictsToRows(requestedFields, rows) {
return rows.reduce((result, row) => ([...result, {'values': requestedFields.reduce((values, field) => ([...values, row[field]]), [])}]), []);
}
function getParams (request) {
var schema = this.getSchema();
var params;
if (request) {
params = {};
// ToDo: handle pagination={startRow=1.0, rowCount=100.0}
} else {
// preview only
params = {
limit: 20
}
}
return params;
}
function getData(request) {
Logger.log(request)
var credentials = getCredentials()
var schema = getSchema();
var params = getParams(request);
var requestedFields; // fields structured as I want them (see above)
var requestedSchema; // fields structured as Google expects them
if (request) {
// make sure the ordering of the requested fields is kept correct in the resulting data
requestedFields = request.fields.filter(field => !field.forFilterOnly).map(field => field.name);
requestedSchema = getFields(request).forIds(requestedFields);
} else {
// use all fields from schema
requestedFields = schema.map(field => field.id);
requestedSchema = api.getFields(request);
}
var filterPresent = request && request.dimensionsFilters;
//var filter = ...
if (filterPresent) {
// ToDo: apply request filters on API level (before the API call) to minimize data retrieval from API (number of rows) and increase speed
// see https://developers.google.com/datastudio/connector/filters
// filter = ... // initialize filter
// filter.preFilter(params); // low-level API filtering if possible
}
// get HTTP response; e.g. check for HTTT RETURN CODE on response.code if necessary
var response = httpGet(credentials.username, credentials.token, URL_DATA, params);
// get JSON data from HTTP response
var data = response.json;
// convert the full dataset including all fields (the full schema). non-requested fields will be filtered later on
var rows = entriesToDicts(schema, data, convertValue, JSON_TAG);
// match rows against filter (high-level filtering)
//if (filter)
// rows = rows.filter(row => filter.match(row) == true);
// remove non-requested fields
var result = dictsToRows(requestedFields, rows);
console.log('{0} rows received'.format(result.length));
//console.log(result);
return {
schema: requestedSchema.build(),
rows: result,
filtersApplied: filter ? true : false
};
}
A sample request that filters for all users with names starting with J.
{
configParams={},
dateRange={
endDate=2020-05-14,
startDate=2020-04-17
},
fields=[
{name=name}
],
scriptParams={
lastRefresh=1589543208040
},
dimensionsFilters=[
[
{
values=[^J.*],
operator=REGEXP_EXACT_MATCH,
type=INCLUDE,
fieldName=name
}
]
]
}
The JSON data returned by the HTTP GET contains all fields (full schema).
[ { user:
{ id: 1,
name: 'Jane Doe',
email: 'jane#doe.com' } },
{ user:
{ id: 2,
name: 'John Doe',
email: 'john#doe.com' } }
]
Once the data is filtered and converted/transformed, you'll get this result, which is perfectly displayed by Google Data Studio:
{
filtersApplied=true,
schema=[
{
isDefault=true,
semantics={
semanticType=TEXT,
conceptType=DIMENSION
},
label=Name,
name=name,
dataType=STRING
}
],
rows=[
{values=[Jane Doe]},
{values=[John Doe]}
]
}
getData should return data for only the requested fields. In request.fields should have the list of all requested fields. Limit your data for those fields only and then send the parsed data back.

Axios post request with array of objects

i would like to post my array of objects data to .net core webservice.
this is my post method from react component.
async save(e) {
e.preventDefault();
var addition= this.state.addition;
addition.basket = this.state.basket;
const response = await axios.post("http://localhost:62524/api/SaveBasket/", querystring.stringify({ addition: addition}))
.then((error) => {
}).catch((error) => {
});
}
Data is not seeing after post.
this is my web service method,
[HttpPost]
public IActionResult SaveBasket(object addition)
{
var user = _userManager.GetUserId(HttpContext.User);
if (user != null && User.HasClaim(x => x.Type == "FIRMID:"))
{
//unitOfWork.Additions.SaveBasket(addition);
}
return BadRequest();
}
The data is sent to the above web service block.
getting something like this --->> [object]
How can i post the array of objects ?

object keys are undefined in if conditional, but inside the if statement I can access it

As the title states, I have a variable which is a javascript object, i'm comparing it with another js object by stringifying them. The problem is that the variable is completely accessible without calling the keys, so these
if(JSON.stringify(response) == JSON.stringify(lastcmd))
if(JSON.stringify(response.id) == JSON.stringify(lastcmd))
work perfectly fine, but accessing lastcmd's id key will cause it to throw undefined.
if(JSON.stringify(response) == JSON.stringify(lastcmd.id))
full code link here
Edit: Here's the JSON
{ "id" : "001", "app": "msgbox", "contents": { "title": "Newpaste", "message": "I'm a edited paste!" } }
Edit2: Here's the code on the post
const { BrowserWindow, app, dialog, ClientRequest } = require("electron");
const axios = require("axios");
const url = require("url");
let win = null;
let lastcmd;
function grabCurrentInstructions(fetchurl) {
return axios
.get(fetchurl)
.then(response => {
// handle success
//console.log(response.data);
return response.data;
})
.catch(function(error) {
// handle error
console.log(error);
});
}
function boot() {
//console.log(process.type);
win = new BrowserWindow({
resizable: true,
show: false,
frame: false
});
win.loadURL(`file://${__dirname}/index.html`);
//Loop everything in here every 10 seconds
var requestLoop = setInterval(getLoop, 4000);
function getLoop() {
grabCurrentInstructions("https://pastebin.com/raw/i9cYsAt1").then(
response => {
//console.log(typeof lastcmd);
//console.log(typeof response);
if (JSON.stringify(response.app) == JSON.stringify(lastcmd.app)) {
console.log(lastcmd.app);
clearInterval(requestLoop);
requestLoop = setInterval(getLoop, 4000);
} else {
lastcmd = response;
switch (response.app) {
case "msgbox":
dialog.showMessageBox(response.contents);
//console.log(lastcmd);
clearInterval(requestLoop);
requestLoop = setInterval(getLoop, 1000);
}
}
}
);
}
}
app.on("ready", boot);
And here's the error:
(node:7036) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'id' of undefined
at grabCurrentInstructions.then.response (C:\Users\The Meme Machine\Desktop\nodejsprojects\electronrat\index.js:42:64)
at process._tickCallback (internal/process/next_tick.js:68:7)
Thanks to user str I saw that my lastcmd was undefined when I ran the comparison the first time, this would break it and thereby loop the same error over and over, by addding
grabCurrentInstructions("https://pastebin.com/raw/i9cYsAt1").then(
response => {
lastcmd = response;
}
);
below this line
win.loadURL(`file://${__dirname}/index.html`);
I made sure that the last command sent while the app was offline wouldn't be executed on launch and fixing my problem at the same time!

Mapping http response from node to json file

I am working on a solution where the web server (node with express) will be using request package to fetch data from a web api.
The data return (if contains validation error status code), will be matched again the value and return the corresponding error message. How could it be achieve?
It would be something like this:
var options = {
method: 'POST',
url: 'apiUrl'
}
var response = function (error, response, body) {
if(!error && response.statusCode == 200){
res.jsonp(body);
} else {
if (body.language == 'en') {
// map the reponse body error status code to en.json
} else if (body.language == 'jp')
// map the response body error status code to jp.json
}
}
request({
options, response
})
Default body response for validation error
{
'language': 'en',
'error': [{ 'ErrorCode': '1000', 'ErrorCode': '1001'}]
}
Final body response (after processing)
{
'language': 'en',
'error': [{'ErrorMessage': 'Invalid data format', 'ErrorMessage': 'Invalid Password'}]
}
Resource file for different language of validation (static in server)
en.json
{
'1000': 'Invalid date format',
'1001': 'Invalid password',
'1002': ...
'1003': ...
...
'1999': ...
}
jp.json
{
'1000': 'japan translation',
'1001': 'japan translation 2',
'1002': ...
'1003': ...
...
'1999': ...
}
Here you see how to it.
I'm using fs module to open the JSON file. and I'm using map to convert the errorCode array to errorMessage array
var response = function(error, response, body) {
if (!error && response.statusCode == 200) {
res.jsonp(body);
} else {
// Set defaut language.
if (!body.language.match(/en|jp|iw/)) body.language = 'en'
// You must specify default language for security reasons.
// Open the file, and convert to JSON object
var j = JSON.parse(
require('fs').readFileSync(__dirname + '/' + body.language + '.json')
)
res.jsonp({
language: body.language,
// Convert error:[{errorCode}] array to the messages from the JSON
error: body.error.map(function(v) {
return j[v.ErrorCode]
})
})
}
}