How can I add custom metadata to calender objects via MS Graph API? - microsoft-graph-api

I'm trying to write a calendar sync using the MS Graph API, i.e. I'm trying to sync events in a local DB to one or several newly created M365 calendars via Graph. In order to keep track of the created calendars, I need to store custom metadata with each calendar. It appears that single-value extended property is the way to add my local ID to the created calendar.
Unfortunately I fail to grasp how to do that: the documentation describes a simple enough request to write the data:
{
"singleValueExtendedProperties": [
{
"id":"String {66f5a359-4659-4830-9070-00047ec6ac6e} Name Color",
"value":"Green"
}
]
}
But the json references a GUID which, in its documentation, references the Exchange Server Protocols Master Property List but I don't understand how they're all connected with each other: do I need to select an ID from the Exchange Server Protocols Master Property List? Is it possible to create a custom GUID? Do I need to create a schema extension (which doesn't seem to be possible for calendar resource types)?
So, how do I add custom metadata to my calendars?

When you create a custom named property, it must be identified by the extended property type, property set identifier, and a string name.
Extended property identifier (id):
<property_type> <property_set_guid> Name <name_of_custom_property>
Property type specifies the data type of a property value. Common values are String, Integer, StringArray and IntegerArray.
Property set is a set of attributes, identified by a GUID. Several of the more common property sets are described here. You can use GUID for PS_PUBLIC_STRINGS ({00020329-0000-0000-C000-000000000046}) property set name.
String name is a name of your custom property.
Example to create an extended property for a calendar.
PATCH https://graph.microsoft.com/v1.0/me/calendars/{calendar-id}
Content-Type: application/json
{
"singleValueExtendedProperties": [
{
"id": "String {00020329-0000-0000-C000-000000000046} Name YourPropertyName",
"value": "PropertyValue" // local ID you want to store
}
]
}
Get property value by using $expand query with $filter inside the expand.
GET https://graph.microsoft.com/v1.0/me/calendars/{calendar-id}?$expand=singleValueExtendedProperties($filter=id eq 'String {00020329-0000-0000-C000-000000000046} Name YourPropertyName')
Resources:
Commonly Used Property Sets

Related

Can't retrieve outlook add-in custom properties from graph API

I need to save a custom property from my outlook add-in and retrieve the this value from graph Api.
I followed MS documentation, this link and this one.
I store the custom property with office.js methods loadCustomPropertiesAsync and customProps.saveAsync
I have checked the value is correctly stored to custom properties (I can read it from add-in when I come back to event)
When I try to check the value from graph API, the event is returned without custom props.
here is the request I use :
{{endpoint}}/Users/bc2d0290-xxx-4041d2d39b66/Events/AAMkADI1YTJjZTI1LWM4YjUtNxxxTvAAA=?$expand=singleValueExtendedProperties($filter=id eq 'String {00020329-0000-0000-C000-000000000046} Name cecp-myAddInManifestId')
What am I doing wrong ?
I found my mistake.
I use custom properties to enrich appointements with conference room.
I tried to retrieve custom props on my server from room eventId instead of organizer eventId

Microsoft Graph $filter by singleValueExtendedProperties and get this extended properties too

I'm exporting app specific events to MS Calendar.
To distinguish them from others (for later updating/removing by the app) I set an extended property for them (with SingleValueExtendedProperties).
I found out how to filter events by the presence (and value) of this extended property
(Get events that have an custom property set by an add-in e.g.)
I also found out how to ask for the value of this property by $expand-ing particular event id -
https://developer.microsoft.com/en-us/graph/docs/api-reference/beta/api/singlevaluelegacyextendedproperty_get
What I can't find is how to get a list of matched events and this extended property for every item. For all the examples I checked (under the second link there're many) it is stated that The response does not include the matching extended property. Why so and how then? Obviously, it would be not very performant to get $filter-ed list and then $expand every item with the separate requests...
I would be very appreciated for any help/hints/thoughts.
According to your description, I assume you want to list the event and extend the property of every item.
We can refer to this document. This document say that,
Using the query parameter $expand allows you to get the specified resource instance expanded with a specific extended property.
Use a $filter and eq operator on the id property to specify the extended property.
This is currently the only way to get the singleValueLegacyExtendedProperty object that represents an extended property.
We can submit this feature request on the User Voice
I found the solution. It could be done with "open extension":
https://developer.microsoft.com/en-us/graph/docs/api-reference/v1.0/api/opentypeextension_post_opentypeextension
The workflow is following:
fill extensions field when creating/updating event:
subject: 'my event',
...
extensions: [{
'#odata.type': 'Microsoft.Graph.OpenTypeExtension',
extensionName: MS_EXTENSION_ID,
appSpecificId: myId
}]
then use a query like this to filter and expand "open extension" values:
url: 'https://graph.microsoft.com/v1.0/me/events'
+ '?$select=subject,start,end'
+ '&$filter=Extensions/any(f:f/id eq \'' + MS_EXTENSION_ID + '\')'
+ '&$expand=Extensions($filter=id eq \'' + MS_EXTENSION_ID + '\')',
MS_EXTENSION_ID could be just a reverse domain name, like Biz.MyCompany.Events

Outlook Rest API push notifications: Filter the notifications based on specific custom property set by outlook add-in

I followed same steps that are mentioned in this question, to filter the push notification events based on custom properties set by outlook add-in.
Below is the resource link that I used while subscribing to push notifications.
https://outlook.office.com/api/v2.0/me/events/?$filter=SingleValueExtendedProperties%2FAny(ep%3A%20ep%2FPropertyId%20eq%20'String%20{00020329-0000-0000-C000-000000000046}%20Name%20cecp-7e248e5e-204e-4e2b-aa0f-788af20fc21c'%20and%20ep%2FValue%20ne%20null)
It's filtering the calendar items that are having custom properties set by add-in, irrespective of whatever custom property it is.
By looking at this resource link, we could say that no where we have mentioned the custom property name. But my add-in sets more than one custom properties to calendar item. I want to filter all calendar items that are having specific custom property. For example, My add-in sets any one of the below custom property to calendar based on business login.
Custom property 1:
var item = Office.context.mailbox.item;
item.loadCustomPropertiesAsync((result) => {
const props = result.value;
props.set("my_prop_one", "test_value_one");
props.saveAsync((saveResult) => console.log("Successfull"));
});
Custom property 2:
var item = Office.context.mailbox.item;
item.loadCustomPropertiesAsync((result) => {
const props = result.value;
props.set("my_prop_two", "test_value_tw");
props.saveAsync((saveResult) => console.log("Successful"));
});
Now I want to filter all calendar items that are having custom property my_prop_one.
EDIT 1:
As suggested by #Jason Johnston in one of the comments, I cross verified the property name and it's GUID using MFCMapi. Both property name and it's GUID values are correct.
MFCMapi data of custom property meetingsetby.
Then I collected data from MFCMapi and prepared the below url to filter calendar items that are having custom property meetingsetby and it's value webex.
https://outlook.office.com/api/v2.0/Me/Events?$filter=SingleValueExtendedProperties%2FAny(ep%3A%20ep%2FPropertyId%20eq%20'String%20{00020329-0000-0000-C000-000000000046}%20Name%20meetingsetby'%20and%20ep%2FValue%20eq%20'webex')
And below is the response from postman when I make the get call using above url.
As you can see, response has empty list even though there is one calendar item with custom property meetingsetby and value webex.
Then I set the SingleValueExtendedProperty to calendar item using outlook Rest API as described in this post. Below is the sample request data,
MFCMapi data of SingleValueExtendedProperty
Then I collected data from MFCMapi and prepared the below url to filter calendar items that are having singleValueExtendedProperty set in above step.
https://outlook.office.com/api/v2.0/Me/Events?$filter=SingleValueExtendedProperties%2FAny(ep%3A%20ep%2FPropertyId%20eq%20'String%20{6666AA44-4659-4830-9070-00047EC6AC6E}%20Name%20RestApiSingleValueExtendedProperty'%20and%20ep%2FValue%20eq%20'Set this property using REST API')
And below is the response from postman when I make the get call using above url.
As you can see, I can successfully filter the calendar items using singleValueExtendedProperty. But my requirement is filter calendar items that are having specific custom property set by my outlook web add-in.
Any suggestion/answers would be more than welcome.
Custom properties set by an add-in (using the CustomProperties interface) are not equivalent to normal MAPI named properties. Essentially what the add-in APIs do is take all of your "custom properties", serialize them as a JSON payload, then save it in a single MAPI named property, which will have the name cecp-{some guid}, and the property set GUID PS_PUBLIC_STRINGS {00020329-0000-0000-C000-000000000046}. The {some-guid} part of the name is equal to the Id of your add-in. This is all specified in MS-OXCEXT section 2.2.5.
So the end result here is that you cannot use $filter on the values you set in the CustomProperties interface, because there is no SingleValueExtendedProperty with that name and value. Instead, there is a single SingleValueExtendedProperty with the name cecp-{some guid}, with a string value that's the JSON serialization of ALL the custom props you set via the CustomProperties interface.
So how can you do what you want? Well, going back to your original URL, you can get all messages that have ANY properties set by your add-in by doing
$filter=SingleValueExtendedProperties/Any
(ep: ep/PropertyId eq 'String {00020329-0000-0000-C000-000000000046}
Name cecp-7e248e5e-204e-4e2b-aa0f-788af20fc21c' and ep/Value ne null)
Replacing the GUID after the cecp- with the GUID ID for your add-in.
But of course you want to find just the ones that have a specific property (meetingsetby) set to a specific value (webex). Unfortunately our API won't support substring searches when filtering the SingleValueExtendedProperties. So what you'd need to do is get all messages with any properties set by your add-in, then do your own filtering logic to find just the ones you want. So basically you would load them in memory, then check the value of that property yourself to find the ones you want.
You can make sure that the value of the property is included in the response by using an $expand clause. Something like this:
?$filter=SingleValueExtendedProperties/Any
(ep: ep/PropertyId eq 'String {00020329-0000-0000-C000-000000000046}
Name cecp-7e248e5e-204e-4e2b-aa0f-788af20fc21c' and ep/Value ne null)
&$expand=SingleValueExtendedProperties($filter=PropertyId eq 'String
{00020329-0000-0000-C000-000000000046} Name cecp-7e248e5e-204e-4e2b-aa0f-788af20fc21c')

Can't get SingleValueExtendedProperties from Outlook contacts for certain data types with GRAPH

I'm trying to get values for PT_DOUBLE and PT_CLSID custom property data types using Microsoft Graph. I have no trouble getting custom properties for PT_LONG (Integer) or PT_UNICODE (String). Integer and String does not work for PT_DOUBLE and PT_CLSID properties, and I get this error:
ErrorInvalidExtendedProperty: The extended property attribute combination is invalid.
The documentation on supported data types is not very clear.
Here's a sample request that works for PT_UNICODE and PT_LONG props:
https://outlook.office.com/api/v2.0/me/contactfolders/{id}/contacts?
$top=1&
$expand=SingleValueExtendedProperties($filter=
(PropertyId eq 'String {1A417774-4779-47C1-9851-E42057495FCA} Name InlineLinks')+OR+
(PropertyId eq 'String {1A417774-4779-47C1-9851-E42057495FCA} Name XrmCompanyPeople')+OR+
(PropertyId eq 'Integer {1A417774-4779-47C1-9851-E42057495FCA} Name XrmContactType'))
I can live without PT_DOUBLE, but I really need to access these PT_CLSID props (String and Guid do not work):
XrmContactId: Tag = 0x86680048;
DASL: http://schemas.microsoft.com/mapi/string/{1A417774-4779-47C1-9851-E42057495FCA}/XrmContactId/0x00000048;
Kind: MNID_STRING
XrmId: Tag = 0x86680048;
DASL: http://schemas.microsoft.com/mapi/string/{1A417774-4779-47C1-9851-E42057495FCA}/XrmId/0x00000048;
Kind: MNID_STRING
Does anyone know the data type name for PT_CLSID or list of supported data types for Microsoft Graph? The Exchange Server Protocols Master Property List is painful to read through and it didn't give me any insights.
For SingleValueLegacyExtendedProperty, both the PropertyID and Value elements are strings.
One bit of clarification, the API you're calling here is the Outlook API and not Graph. While they provide similar functionality, they are distinct endpoints. Extended Properties in Graph also only supports string values.

Objective-C get a class property from string

I've heard a number of similar questions for other languages, but I'm looking for a specific scenario.
My app has a Core Data model called "Record", which has a number of columns/properties like "date, column1 and column2". To keep the programming clean so I can adapt my app to multiple scenarios, input fields are mapped to a Core Data property inside a plist (so for example, I have a string variable called "dataToGet" with a value of 'column1'.
How can I retrieve the property "column1" from the Record class by using the dataToGet variable?
The Key Value Coding mechanism allows you to interact with a class's properties using string representations of the property names. So, for example, if your Record class has a property called column1, you can access that property as follows:
NSString* dataToGet = #"column1";
id value = [myRecord valueForKey:dataToGet];
You can adapt that principle to your specific needs.

Resources