Autodesk.DesignAutomation returning Unexpected token S in JSON at position 0 when calling the workitem api - autodesk-forge

I am facing a new issue with a fetch
handleSendToForge(e) {
e.preventDefault();
let formData = new FormData();
formData.append('data', JSON.stringify({
Width: this.state.Width,
Length: this.state.Length,
Depth: this.state.Depth,
Thickness: this.state.Thickness,
BottomThickness: this.state.BottomThickness,
rebarSpacing: this.state.rebarSpacing,
outputrvt: this.state.outputrvt,
bucketId: this.state.bucketId,
activityId: 'RVTDrainageWebappActivity',
objectId: 'template.rvt'
}));
this.setState({
form: formData
})
fetch('designautomation', {
method: 'POST',
body: formData,
//headers: {
// //'Content-Type': 'application/json'
// 'Content-Type': 'application/x-www-form-urlencoded',
//},
})
.then(response => response.json())
.then(data => { console.log(data) })
.catch(error => console.log(error));
}
and the code for the controller is pretty standard and is slightly modified from one of the forge examples
[HttpPost]
[Route("designautomation")]
public async Task<IActionResult> Test([FromForm] StartWorkitemInput input)
{
JObject workItemData = JObject.Parse(input.data);
double Width = workItemData["Width"].Value<double>();
double Length = workItemData["Length"].Value<double>();
double Depth = workItemData["Depth"].Value<double>();
double Thickness = workItemData["Thickness"].Value<double>();
double BottomThickness = workItemData["BottomThickness"].Value<double>();
double rebarSpacing = workItemData["rebarSpacing"].Value<double>();
string outputrvt = workItemData["outputrvt"].Value<string>();
string activityId = workItemData["activityId"].Value<string>();
string bucketId = workItemData["bucketId"].Value<string>();
string objectId = workItemData["objectId"].Value<string>();
// basic input validation
string activityName = string.Format("{0}.{1}", NickName, activityId);
string bucketKey = bucketId;
string inputFileNameOSS = objectId;
// OAuth token
dynamic oauth = await OAuthController.GetInternalAsync();
// prepare workitem arguments
// 1. input file
dynamic inputJson = new JObject();
inputJson.Width = Width;
inputJson.Length = Length;
inputJson.Depth = Depth;
inputJson.Thickness = Thickness;
inputJson.BottomThickness = BottomThickness;
inputJson.rebarSpacing = rebarSpacing;
inputJson.outputrvt = outputrvt;
XrefTreeArgument inputFileArgument = new XrefTreeArgument()
{
Url = string.Format("https://developer.api.autodesk.com/oss/v2/buckets/aecom-bucket-demo-library/objects/{0}", objectId),
Headers = new Dictionary<string, string>()
{
{ "Authorization", "Bearer " + oauth.access_token }
}
};
// 2. input json
XrefTreeArgument inputJsonArgument = new XrefTreeArgument()
{
Headers = new Dictionary<string, string>()
{
{"Authorization", "Bearer " + oauth.access_token }
},
Url = "data:application/json, " + ((JObject)inputJson).ToString(Formatting.None).Replace("\"", "'")
};
// 3. output file
string outputFileNameOSS = outputrvt;
XrefTreeArgument outputFileArgument = new XrefTreeArgument()
{
Url = string.Format("https://developer.api.autodesk.com/oss/v2/buckets/{0}/objects/{1}", bucketKey, outputFileNameOSS),
Verb = Verb.Put,
Headers = new Dictionary<string, string>()
{
{"Authorization", "Bearer " + oauth.access_token }
}
};
// prepare & submit workitem
// the callback contains the connectionId (used to identify the client) and the outputFileName of this workitem
//string callbackUrl = string.Format("{0}/api/forge/callback/designautomation?id={1}&bucketKey={2}&outputFileName={3}", OAuthController.FORGE_WEBHOOK_URL, browerConnectionId, bucketKey, outputFileNameOSS);
WorkItem workItemSpec = new WorkItem()
{
ActivityId = activityName,
Arguments = new Dictionary<string, IArgument>()
{
{ "rvtFile", inputFileArgument },
{ "jsonFile", inputJsonArgument },
{ "result", outputFileArgument }
///{ "onComplete", new XrefTreeArgument { Verb = Verb.Post, Url = callbackUrl } }
}
};
DesignAutomationClient client = new DesignAutomationClient();
client.Service.Client.BaseAddress = new Uri(#"http://localhost:3000");
WorkItemStatus workItemStatus = await client.CreateWorkItemAsync(workItemSpec);
return Ok();
}
Any idea why is giving me this error? I have tested the api using postman and it works fine but when I try to call that from a button I keep receive this error. Starting the debug it seems that the url is written correctly. Maybe it is a very simple thing that i am missing.
Cheers!

OK solved...
I was missing to add the service in the Startup and also the Forge connection information (clientid, clientsecret) in the appsettings.json
Now I need to test the AWS deployment and I guess I am done!

Related

Asp.Net core Web API: how can I export and import JSON from the external REST APIs?

ASP.Net Core WebAPI is being built to fetch JSON from external REST API endpoint. I would like to save the JSON and reload it
At present, I am fetching the JSON from an external REST API endpoint using the following code:
public async Task<List<Weather>> Get(string cities)
{
List<Weather> weathers = new List<Weather>();
var options = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
};
foreach (var city in cities.Split(";"))
{
string APIURL = $"?key={this.apiKey}&q={city}";
var response = await _httpClient.GetAsync(APIURL);
if (response.IsSuccessStatusCode)
{
var responses = await response.Content.ReadAsStreamAsync();
var weather = await JsonSerializer.DeserializeAsync<Weather>(responses, options);
weathers.Add(weather);
}
}
return weathers;
}
that returns the following JSON
[
{
"location":{
"name":"Chennai",
"region":"Tamil Nadu",
...
},
"current":{
"last_updated_epoch":1663601400,
"last_updated":"2022-09-19 21:00",
...
}
},
{
"location":{
"name":"Mumbai",
"region":"Maharashtra",
..
},
"current":{
"last_updated_epoch":1663602300,
"last_updated":"2022-09-19 21:15",
..
}
}
]
How can I export and import JSON ?
Update: I have updated the code as mentioned below
public static class JsonFileUtils
{
private static readonly JsonSerializerSettings _options
= new() { NullValueHandling = NullValueHandling.Ignore };
public static void StreamWrite(object obj, string fileName)
{
using var streamWriter = File.CreateText(fileName);
using var jsonWriter = new JsonTextWriter(streamWriter);
JsonSerializer.CreateDefault(_options).Serialize(jsonWriter, obj);
}
public static async Task StreamWriteAsync(object obj, string fileName)
{
await Task.Run(() => StreamWrite(obj, fileName));
}
}
and used it like
public async Task<List<Weather>> Get(string cities)
{
List<Weather> weathers = new List<Weather>();
var options = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
};
foreach (var city in cities.Split(";"))
{
string APIURL = $"?key={this.apiKey}&q={city}";
var response = await _httpClient.GetAsync(APIURL);
if (response.IsSuccessStatusCode)
{
var responses = await response.Content.ReadAsStreamAsync();
var weather = await JsonSerializer.DeserializeAsync<Weather>(responses, options);
weathers.Add(weather);
}
}
var fileName = "weathers.json";
await JsonFileUtils.StreamWriteAsync(weathers, fileName);
return weathers;
}
to upload the file
[HttpPost("upload", Name = "upload")]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(List<Weather>))]
[ProducesResponseType(typeof(string), StatusCodes.Status400BadRequest)]
public async Task<IActionResult> UploadFile(
IFormFile file,
CancellationToken cancellationToken)
{
string fileContent = null;
using (var reader = new StreamReader(file.OpenReadStream()))
{
fileContent = reader.ReadToEnd();
}
var result = JsonConvert.DeserializeObject<List<Weather>>(fileContent);
return Ok(result);
}

Why isn't my function returning the proper JSON data and how can I access it?

I'm running services to retrieve data from an API. Here is one of the services:
robotSummary(core_id, channel_name){
const params = new HttpParams()
var new_headers = {
'access-token': ' '
};
this.access_token = sessionStorage.getItem('access-token');
new_headers['access-token'] = this.access_token;
const myObject: any = {core_id : core_id, channel_name: channel_name};
const httpParams: HttpParamsOptions = { fromObject: myObject } as HttpParamsOptions;
const options = { params: new HttpParams(httpParams), headers: new_headers };
return this.http.get(this.baseURL + 'web_app/robot_summary/',options)
.subscribe(
res => console.log(res),
)
}
}
The data shows up properly on the console, but I still can't access the individual keys:
Here is how I call it:
ngOnInit(): void{
this.login.getData(this.username, this.password).subscribe((data) => {
this.robotSummaryData = this.getRobotSummary.robotSummary(this.core_id, this.channel_name);
console.log("robosummary"+ this.robotSummaryData)
});
}
When I call this function and assign it to a variable, it shows up on console as [object Object]. When I tried to use JSON.parse, it throws the error: type subscription is not assignable to parameter string. How can I access the data? I want to take the JSON object and save it as an Object with appropriate attributes. Thanks!
Do not subscribe inside your service, do subscribe in your component, change your service as follows,
robotSummary(core_id, channel_name){
const params = new HttpParams()
var new_headers = {
'access-token': ' '
};
this.access_token = sessionStorage.getItem('access-token');
new_headers['access-token'] = this.access_token; const myObject: any = { core_id: core_id, channel_name: channel_name };
const httpParams: HttpParamsOptions = { fromObject: myObject } as HttpParamsOptions;
const options = { params: new HttpParams(httpParams), headers: new_headers };
return this.http.get(this.baseURL + 'web_app/robot_summary/', options)
.map((response: Response) => response);
}
and then in your component,
ngOnInit(){
this.api..getRobotSummary.robotSummary(this.core_id, this.channel_name).subscribe((data) => {
this.data = data;
console.log(this.data);
});
}

Cakephp object mapper?

I have the following code in android to send to my cakephp server
val params = JSONObject()
val siteId = sharedPref.getInt("site_id", 0)
try {
params.put("photo", encodeImage)
params.put("lat", latitude)
params.put("lng", longitude)
params.put("status", status)
params.put("site_id", siteId)
} catch (e: JSONException) {
Log.e("JsonException", e.toString())
}
val queue = Volley.newRequestQueue(this#CameraActivity)
val request = object : JsonObjectRequest(Request.Method.POST, ROOT_URL + TRANSACTION,
params, Response.Listener<JSONObject> { response ->
// startActivity(myIntent)
}, Response.ErrorListener {
Toast.makeText(this#CameraActivity, "That didn't work!", Toast.LENGTH_SHORT).show()
}) {
#Throws(AuthFailureError::class)
override fun getHeaders(): MutableMap<String, String> {
val headers = HashMap<String, String>()
headers.put("Accept", "application/json")
headers.put("Content-Type", "application/json; charset=utf-8")
headers.put("Authorization", "Bearer "+ token) // Figure out a way to get JWT
return headers
}
}
And I have this code on cakephp controller to receive it
$transaction = $this->Transactions->newEntity();
if($this->request->is('post')){
$transaction->lat = $this->request->getData('lat');
$transaction->lng = $this->request->getData('lng');
$photo = $this->request->getData('photo');
$transaction->status = $this->request->getData('status');
$decoded = base64_decode($photo);
$transaction->employee_id = $this->Auth->user('id');
$transaction->project_id = $this->Auth->user('project_id');
$transaction->site_id = $this->request->getData('site_id');
if ($this->Transactions->save($transaction)) {
$this->Auth->logout();
$this->set([
'success' => true,
'_serialize' => ['success']
]);
}
}
The problem is on the server side I do not want to equate every request to a cakephp entity variable. Is there a way I can just do an object mapping so i do not need to do the unnecessary equating at the cakephp controller?

POST data to web service HttpWebRequest Windows Phone 8

I've been trying without success today to adapt this example to POST data instead of the example GET that is provided.
http://blogs.msdn.com/b/andy_wigley/archive/2013/02/07/async-and-await-for-http-networking-on-windows-phone.aspx
I've replaced the line:
request.Method = HttpMethod.Get;
With
request.Method = HttpMethod.Post;
But can find no Method that will allow me to stream in the content I wish to POST.
This HttpWebRequest seems a lot cleaner than other ways e.g. sending delegate functions to handle the response.
In Mr Wigley's example code I can see POST so it must be possible
public static class HttpMethod
{
public static string Head { get { return "HEAD"; } }
public static string Post { get { return "POST"; } }
I wrote this class some time ago
public class JsonSend<I, O>
{
bool _parseOutput;
bool _throwExceptionOnFailure;
public JsonSend()
: this(true,true)
{
}
public JsonSend(bool parseOutput, bool throwExceptionOnFailure)
{
_parseOutput = parseOutput;
_throwExceptionOnFailure = throwExceptionOnFailure;
}
public async Task<O> DoPostRequest(string url, I input)
{
var client = new HttpClient();
CultureInfo ci = new CultureInfo(Windows.System.UserProfile.GlobalizationPreferences.Languages[0]);
client.DefaultRequestHeaders.Add("Accept-Language", ci.TwoLetterISOLanguageName);
var uri = new Uri(string.Format(
url,
"action",
"post",
DateTime.Now.Ticks
));
string serialized = JsonConvert.SerializeObject(input);
StringContent stringContent = new StringContent(
serialized,
Encoding.UTF8,
"application/json");
var response = client.PostAsync(uri, stringContent);
HttpResponseMessage x = await response;
HttpContent requestContent = x.Content;
string jsonContent = requestContent.ReadAsStringAsync().Result;
if (x.IsSuccessStatusCode == false && _throwExceptionOnFailure)
{
throw new Exception(url + " with POST ends with status code " + x.StatusCode + " and content " + jsonContent);
}
if (_parseOutput == false){
return default(O);
}
return JsonConvert.DeserializeObject<O>(jsonContent);
}
public async Task<O> DoPutRequest(string url, I input)
{
var client = new HttpClient();
CultureInfo ci = new CultureInfo(Windows.System.UserProfile.GlobalizationPreferences.Languages[0]);
client.DefaultRequestHeaders.Add("Accept-Language", ci.TwoLetterISOLanguageName);
var uri = new Uri(string.Format(
url,
"action",
"put",
DateTime.Now.Ticks
));
string serializedObject = JsonConvert.SerializeObject(input);
var response = client.PutAsync(uri,
new StringContent(
serializedObject,
Encoding.UTF8,
"application/json"));
HttpResponseMessage x = await response;
HttpContent requestContent = x.Content;
string jsonContent = requestContent.ReadAsStringAsync().Result;
if (x.IsSuccessStatusCode == false && _throwExceptionOnFailure)
{
throw new Exception(url + " with PUT ends with status code " + x.StatusCode + " and content " + jsonContent);
}
if (_parseOutput == false){
return default(O);
}
return JsonConvert.DeserializeObject<O>(jsonContent);
}
}
Then when I want to call it, I can use it as following :
JsonSend<User, RegistrationReceived> register = new JsonSend<User, RegistrationReceived>();
RegistrationReceived responseUser = await register.DoPostRequest("http://myurl", user);

When uploading Photo to Web API always 0 bytes

I have the following, and it uploads without errors, but the image is always 0 bytes.
Windows Phone App (this is called after selecting or taking a photo):
private void AddImage(PhotoResult e)
{
if (e.TaskResult == TaskResult.OK)
{
string serviceUri = Globals.GreedURL + #"API/UploadPhoto/test5.jpg";
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(serviceUri);
request.Method = "POST";
request.BeginGetRequestStream(result =>
{
Stream requestStream = request.EndGetRequestStream(result);
e.ChosenPhoto.CopyTo(requestStream);
requestStream.Close();
request.BeginGetResponse(result2 =>
{
try
{
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(result2);
if (response.StatusCode == HttpStatusCode.Created)
{
this.Dispatcher.BeginInvoke(() =>
{
MessageBox.Show("Upload completed.");
});
}
else
{
this.Dispatcher.BeginInvoke(() =>
{
MessageBox.Show("An error occured during uploading. Please try again later.");
});
}
}
catch
{
this.Dispatcher.BeginInvoke(() =>
{
MessageBox.Show("An error occured during uploading. Please try again later.");
});
}
e.ChosenPhoto.Close();
}, null);
}, null);
}
And here is the Web API:
public class UploadPhotoController : ApiController
{
public HttpResponseMessage Post([FromUri]string filename)
{
var task = this.Request.Content.ReadAsStreamAsync();
task.Wait();
Stream requestStream = task.Result;
// Retrieve storage account from connection string.
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(ConfigurationManager.ConnectionStrings["StorageConnectionString"].ConnectionString);
// Create the blob client.
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
// Retrieve reference to a previously created container.
CloudBlobContainer container = blobClient.GetContainerReference("profilepics");
container.CreateIfNotExists();
var permissions = container.GetPermissions();
permissions.PublicAccess = BlobContainerPublicAccessType.Blob;
container.SetPermissions(permissions);
string uniqueBlobName = string.Format("test.jpg");
CloudBlockBlob blob = container.GetBlockBlobReference(uniqueBlobName);
blob.Properties.ContentType = "image\\jpeg";
blob.UploadFromStream(task.Result);
HttpResponseMessage response = new HttpResponseMessage();
response.StatusCode = HttpStatusCode.Created;
return response;
}
}
Any ideas?
Any help would be appreciated.