Unable to create ListItems with 'Objects' using Microsoft Graph Api - javascript

I am trying to create a SharePoint ListItem using Microsoft Graph.
The methods I use to POST/PATCH ListItems are working unless I apply these methods to a list that contain objects (like Groups, Users or even Images).
In my examples, I'll be posting, patching or getting from /beta/sites/root/lists/1231231231234/items/4/fields.
SharePoint ListItem
{
"#odata.context":
"https://graph.microsoft.com/beta/$metadata#sites('root')/lists('1234123412341234')/items('4')/fields/$entity",
"#odata.etag": "\"123412341234,18\"",
"Title": "Test Title",
"description": "Some random description",
"assignedGroups": [
{
"LookupId": 7818,
"LookupValue": "7818",
"Email": "DemoGroep#12341234.onmicrosoft.com"
},
{
"LookupId": 7822,
"LookupValue": "7822",
"Email": "TestDemo#12341234.onmicrosoft.com"
}
],
"startDate": "2018-05-15T07:00:00Z",
"endDate": "2018-08-18T07:00:00Z",
"alwaysAvailable": false,
"id": "4",
"ContentType": "Item",
"Modified": "2018-05-17T13:27:21Z",
"Created": "2018-04-03T09:34:49Z",
"AuthorLookupId": "7688",
"EditorLookupId": "5222",
"_UIVersionString": "1.0",
"Attachments": false,
"Edit": "",
"LinkTitleNoMenu": "Test123123",
"LinkTitle": "Test123123",
"ItemChildCount": "0",
"FolderChildCount": "0",
"_ComplianceFlags": "",
"_ComplianceTag": "",
"_ComplianceTagWrittenTime": "",
"_ComplianceTagUserId": "",
"AppEditorLookupId": "25"
}
Working example (Note: This works because I update a simple field like 'Title' which is of type String)
{
Title: "SomeNewTitle"
}
Not working Example (returns 400 'The request is malformed or incorrect.')
{
assignedGroups: [{"Email": "Test1003#12341234o.onmicrosoft.com"}]
}
I tried multiple kinds of objects here but it never works.. even empty arrays (to clear group memberships) is returning 400 status.
I have a feeling that this is a limitation/bug in the Graph API

This is unfortunately a known issue with Microsoft Graph's SharePoint API. There is a UserVoice request to fix this, it could absolutely use more votes.

Try the PATCH body like this:
//PATCH
{
assignedGroups: {"Email": "Test1003#StichtingNuovo.onmicrosoft.com"}
}
Because in the listItem it is returning an array of assignedGroups but you are only updating one. If you needed to update multiple I believe the call would be:
//PATCH
{
assignedGroups: [{"Email": "Test1003#StichtingNuovo.onmicrosoft.com"},
{"Email": "AnotherEmail#microsoft.com"}
]
}

Related

jquery/ajax - how to iterate through a json message with duplicate keys?

I receive with my ajax post request a message with values to display. This json response message looks like this:
{
"line": {
"name": "Google item",
"images": {
"element": {
"order": "1",
"link": "https://google.com/1.jpg",
"name": "1.jpg"
},
"element": {
"order": "2",
"link": "https://google.com/2.jpg",
"name": "2.jpg"
},
"element": {
"order": "3",
"link": "https://google.com/3.jpg",
"name": "3.jpg"
},
"element": {
"order": "4",
"link": "https://google.com/4.jpg",
"name": "4.jpg"
},
"element": {
"order": "5",
"link": "https://google.com/5.jpg",
"name": "5.jpg"
}
},
"features": {
"element": {
"name": "1",
"order": "1"
},
"element": {
"name": "2",
"order": "2"
},
"element": {
"name": "3",
"order": "3"
},
"element": {
"name": "4",
"order": "4"
}
},
"purchasing_price": "10",
"selling_price": "20",
"ftp_path": "google/item",
"description": ""
}
}
I'm in development and have not so much experience with json in jquery/ajax.
I tried this:
function parseContent(content){
$("#name").val(content.line.name);
$("#ftp_path").val(content.line.ftp_path);
$("#html_description").val(content.line.description);
$("#feature").remove();
$.each(content.line.features, function(k, v){
$("#features").append('<input type="text" class="form-control mt-3" id="feature" value="' + v.name + '" required>');
alert(v.name );
});
}
My problem is, the variable content contains just the last image und feature element. But in chrome/network I could see, the complete message has been received.
So I found out there is a parsing issue: Parsed JSON contains only the last element.
But how can I fix this in my case, to iterate through all elements?
The JSON specification says:
The names within an object SHOULD be unique.
The names in those objects are not.
SHOULD means:
that there
may exist valid reasons in particular circumstances to ignore a
particular item, but the full implications must be understood and
carefully weighed before choosing a different course.
The implications here are that every JSON parser (that I'm aware of at least) will ignore all but one of the values with duplicate names in an object.
If you really need to deal with that data then you are going to have to either track down a parser which can handle it (I'm not aware of any) or write a custom JSON parser which can (you'll also need to decide what data structure you want to generate from it because JS can't have duplicate property names in objects either). There are a number of JSON parsers on npm you might want to examine the source code of as a starting point.
A better solution would be to change whatever is generating the source data to produce a sensible format that doesn't violate a SHOULD requirement. Replacing the duplicate property names with an array for example.

How to POST relation in Strapi

I'm trying to do a POST to the Strapi API and can't seem to figure out how to attach a 'has and belongs to many' (many to many) relationship.
I've already tried the following body's:
events: ["ID", "ID"]
name: "name"
&
events: [ID, ID]
name: "name"
Which regarding the docs should be right, I think.
There's no error, I get a '200 OK' response. It adds the record but without the relations.
Event.settings.json:
{
"connection": "default",
"collectionName": "events",
"info": {
"name": "event",
"description": ""
},
"options": {
"increments": true,
"timestamps": [
"created_at",
"updated_at"
],
"comment": ""
},
"attributes": {
"name": {
"type": "string"
},
"artists": {
"collection": "artist",
"via": "events",
"dominant": true
}
}
}
Artist.settings.json:
{
"connection": "default",
"collectionName": "artists",
"info": {
"name": "artist",
"description": ""
},
"options": {
"increments": true,
"timestamps": [
"created_at",
"updated_at"
],
"comment": ""
},
"attributes": {
"name": {
"required": true,
"type": "string"
},
"events": {
"collection": "event",
"via": "artists"
}
}
}
I'm using the standard SQLite database, strapi version 3.0.0-beta.13 and tried the request through Postman, HTML & curl.
I would love to know how to attach the relation on POST
Update 23-07:
Did a fresh install of Strapi and now everything is working.
I think it's because your set you ID as a String instead of an Integer
{
events: [1, 2],
name: "My name"
}
And here 1 and 2 are the IDs of events you want to add.
Late reply. Hoping this might help someone!
Right now I am using Strapi v4.3.2 and was facing the same issue. I overcame this by overriding the default core controller for create as explained in official docs. Relations are now visible!
async create(ctx) {
const { data } = ctx.request.body;
const response = await strapi.entityService.create(
"api::collection.collection",
{
data: data,
}
);
return {response}
}
This is (still? again?) a bug in Strapi, see: https://github.com/strapi/strapi/issues/12238
As a workaround you need to add the find-permission to the user / role who is performing the request for the related content type (you want to check first if this is a security issue for your scenario or not - alternatively you might want to try Paratron's approach which is described in the comments).

Dialogflow html/js card json value v1

I am trying to access the card json value, to no avail.
In my scenario, I am asking the bot about "weather in London" and it replies back with "It is currently 9 degrees celcius in London." via the webhook.
Which is correct and dynamic.
However, I am trying to also pass the values to a card too.
In the json reply, I do get the card as so
{
"id": "REMOVED",
"timestamp": "2017-12-05T11:10:52.033Z",
"lang": "en",
"result": {
"source": "agent",
"resolvedQuery": "weather in london",
"action": "sayWeather",
"actionIncomplete": false,
"parameters": {
"geo-city": "London"
},
"contexts": [],
"metadata": {
"intentId": "REMOVED",
"webhookUsed": "true",
"webhookForSlotFillingUsed": "false",
"webhookResponseTime": 626,
"intentName": "Weather"
},
"fulfillment": {
"speech": "It is currently 9 degrees celcius in London.",
"source": "agent",
"displayText": "It is currently 9 degrees celcius in London.",
"messages": [
{
"type": 0,
"speech": "It is currently 9 degrees celcius in London."
}
],
"data": {
"items": [
{
"simpleResponse": {
"textToSpeech": "This is the first simple response for a basic card"
}
},
{
"basicCard": {
"title": "Title: this is a title",
"formattedText": "This is a basic card. Text in a\n basic card can include \"quotes\" and most other unicode characters\n including emoji 📱. Basic cards also support some markdown\n formatting like *emphasis* or _italics_, **strong** or __bold__,\n and ***bold itallic*** or ___strong emphasis___ as well as other things\n like line \nbreaks",
"subtitle": "This is a subtitle",
"image": {
"url": "https://developers.google.com/actions/images/badges/XPM_BADGING_GoogleAssistant_VER.png",
"accessibilityText": "Image alternate text"
},
"buttons": [
{
"title": "This is a button",
"openUrlAction": {
"url": "https://assistant.google.com/"
}
}
]
}
},
{
"simpleResponse": {
"textToSpeech": "This is the 2nd simple response ",
"displayText": "This is the 2nd simple response"
}
}
]
}
},
"score": 1
},
"status": {
"code": 200,
"errorType": "success",
"webhookTimedOut": false
},
"sessionId": "REMOVED"
}
Accessing the value of speech using data.result.fulfillment.speech works fine.
However, when using data.result.fulfillment.data.items.basicCard.image.url it just doesnt work. And if I go up several levels, I do get:
[object Object]
Your help is appreciated.
The items attribute is a list and not an object. As such, you'll have to use a numerical index to retrive the data. In the example you provided the index of the basicCard object is second so your code should look something like this:
data.result.fulfillment.data.items[1].basicCard.image.url
Notice the [1] after items.
Bear in mind that if the order of this list changes you may no longer be retrieving a basicCard object so you may want to add some checking to make sure you're retrieving the data you want.

Writing JSON array to object

I have some JSON which looks like this.
[
{
"items": [
{
"id": "xxxx",
"description": {
"style": "",
"specs": ""
}
},
{
"id": "xxxx",
"description": {
"style": "",
"specs": ""
}
}
],
"category": "xxxxxx",
"name": "xxxxxx"
},
{
"items": [
{
"id": "xxxx",
"description": {
"style": "",
"specs": ""
}
},
{
"id": "xxxx",
"description": {
"style": "",
"specs": ""
}
}
],
"category": "xxxxxx",
"name": "xxxxxx"
}
]
It's being passed to me as 'newItem'. And is being set twice in the existing code I'm working on:
that.cart.addItem(newItem.toObject());
And later:
that.origCart.replaceWith(that.cart);
This traditionally has worked fine when 'items' was a flat list. However, the JSON above is the new JSON format and therefor I need to pass 'items' for each category/name.
Inside the 'for' loop I have this outputting what I need for each.(I need to keep them separated.)
newItem.items
However, when I attempt to perform the following I get a Type Error. (Yes, I'm going to have multiple 'carts' once I get this working.)
that.cart.addItem(newItem.items.toObject());
TypeError: newItem.items.toObject is not a function
What can I do to get 'newItem.items' to the proper type, or what operation can I substitute for to get these set properly? I tried a bunch of things I found online without success and now I'm turning to the experts. Just not my forte (yet).
It looks like you're trying to call an items function from the newItems object even though items is an Array. Try the following:
that.cart.addItem(newItem.items);

Rally: Fields from multiple tables

I am using the Rally WSAPI 2.0p5 with and the JSON return
I am looking to get fields from multiple tables in a single response. Is this possible? For example I am trying to get the User Story and also get the Iteration.State in the same data response. I know it is possible to do client side and if that is the only way. Can someone provide and example how I handle the async response to build the table (array).
Simply add State to the list of attributes included in your fetch. Rally's WSAPI will populate the value for sub objects even if the main type being queried does not have that field.
launch: function() {
var userStories = Ext.create('Rally.data.WsapiDataStore', {
model: 'HierarchicalRequirement',
fetch: ['Iteration', 'State'],
autoLoad: true,
filters: [
{
property: 'Iteration.State',
value: 'Accepted'
}
],
limit: 10000,
listeners: { load: this._onDataLoaded, scope: this }
});
}
As a follow up for my original question. I recently came across the alpha release of the Batch Query WSAPI in Rally's WSAPI documentation. I would suggest the usage of the Batch Query to retrieve multiple Object Models in a single response.
As an example to get User Stories and get the Iteration Status in a single query.
{
"stories" : "/HierarchicalRequirement?fetch=Name,Iteration,State&query=(Iteration.State = Accepted)"
}
The result is something that is more usable and doesn't require multiple queries to the server. i.e.
"Results": [{
"_rallyAPIMajor": "1",
"_rallyAPIMinor": "40",
"_ref": "https://rally1.rallydev.com/slm/webservice/x/hierarchicalrequirement/xxxxxxxx.js",
"_objectVersion": "17",
"_refObjectName": "<user role> I would like <feature> for <benifit>",
"Name": "As a <user role> I would like <feature> for <benifit>",
"Iteration": {
"_rallyAPIMajor": "1",
"_rallyAPIMinor": "40",
"_ref": "https://rally1.rallydev.com/slm/webservice/x/iteration/xxxxxxxx.js",
"_objectVersion": "4",
"_refObjectName": "Sprint #",
"Name": "Sprint #",
"State": "Accepted",
"_type": "Iteration"
},
"Project": {
"_rallyAPIMajor": "1",
"_rallyAPIMinor": "40",
"_ref": "https://rally1.rallydev.com/slm/webservice/x/project/xxxxxxxx.js",
"_refObjectName": "Name",
"_type": "Project"
},
"_type": "HierarchicalRequirement"
},
....
]
For more information and a few resources:
https://rally1.rallydev.com/slm/doc/webservice/index.jsp?version=1.40
https://rally1.rallydev.com/slm/doc/webservice/batch.jsp
https://rally1.rallydev.com/slm/doc/webservice/BatchScratchPad.jsp

Categories