How to retrieve extended properties for calendar event (by name)? - microsoft-graph-api

I have an Exchange calendar populated though Exchanges Web Services (EWS) UpdateItem SOAP calls containing:
(Example here for an integer TTID and a TTSyncID string field)
<mes:UpdateItem ConflictResolution="AlwaysOverwrite" SendMeetingInvitationsOrCancellations="SendToNone">
<mes:ItemChanges>
<typ:ItemChange>
<typ:ItemId Id="%s" ChangeKey="%s" />
<typ:Updates>
<typ:SetItemField>
<typ:ExtendedFieldURI DistinguishedPropertySetId="PublicStrings" PropertyName="TTID" PropertyType="Integer"/>
<typ:CalendarItem>
<typ:ExtendedProperty>
<typ:ExtendedFieldURI DistinguishedPropertySetId="PublicStrings" PropertyName="TTID" PropertyType="Integer"/>
<typ:Value>10</typ:Value>
</typ:ExtendedProperty>
</typ:CalendarItem>
</typ:SetItemField>
<typ:SetItemField>
<typ:ExtendedFieldURI DistinguishedPropertySetId="PublicStrings" PropertyName="TTSyncID" PropertyType="String"/>
<typ:CalendarItem>
<typ:ExtendedProperty>
<typ:ExtendedFieldURI DistinguishedPropertySetId="PublicStrings" PropertyName="%s" PropertyType="String"/>
<typ:Value>SomeStringData</typ:Value>
</typ:ExtendedProperty>
</typ:CalendarItem>
</typ:SetItemField>
</typ:Updates>
</typ:ItemChange>
</mes:ItemChanges>
</mes:UpdateItem>
In EWS they came back in the GetItem SOAP requests as
<ExtendedProperty>
<ExtendedFieldURI DistinguishedPropertySetId="PublicStrings" PropertyName="TTID" PropertyType="Integer"/>
<Value>10</Value>
</ExtendedProperty>
<ExtendedProperty>
<ExtendedFieldURI DistinguishedPropertySetId="PublicStrings" PropertyName="TTSyncID" PropertyType="String"/>
<Value>SomeStringData</Value>
</ExtendedProperty>
I'm now trying to retrieve these with the other event properties through Postman calls to the MS Graph API.
From what I understand I have to use Outlook extended properties and not Open extensions to keep this backward compatible (correct me if I'm wrong).
But I can't get this to work, because the singleValueExtendedProperties expansion seems to insist on MAPIPropertyTpes and GUIDs. If I call
https://graph.microsoft.com/v1.0/users/{{UserID}}/calendar/events/{{TTSyncedEventID}}?$expand=singleValueExtendedProperties($filter=id eq '{{extensionID}}')
with {{extensionID}} = TTSyncID or TTID, I get
{
"error": {
"code": "ErrorInvalidProperty",
"message": "PropertyId values may only be in one of the following formats: 'MapiPropertyType namespaceGuid Name propertyName', 'MapiPropertyType namespaceGuid Id propertyId' or 'MapiPropertyType propertyTag'."
}
}
Can I somehow retrieve these namespaceGuid and use those (as suggested here?
Is there an easier way referencing the properties with the human-readable TTSyncID or TTID?

Based on this, namespace GUID for public strings property sets is {00020329-0000-0000-C000-000000000046}.
If you use the following form of URL
https://graph.microsoft.com/v1.0/users/{{UserID}}/calendar/events/{{TTSyncedEventID}}?$expand=singleValueExtendedProperties($filter=id eq 'MapiPropertyType namespaceGuid Name propertyName')
You should be able to get the value of TTID property
https://graph.microsoft.com/v1.0/users/{{UserID}}/calendar/events/{{TTSyncedEventID}}?$expand=singleValueExtendedProperties($filter=id eq 'Integer {00020329-0000-0000-C000-000000000046} Name TTID')
and get the value of TTSyncID property
https://graph.microsoft.com/v1.0/users/{{UserID}}/calendar/events/{{TTSyncedEventID}}?$expand=singleValueExtendedProperties($filter=id eq 'String {00020329-0000-0000-C000-000000000046} Name TTSyncID')

You can look at existing messages with these properties set with MFCMAPI or OutlookSpy (I am its author, click IMessage button to see Extended MAPI properties). In OutlookSpy you can also construct a Graph query and specify any MAPI property (fixed or named) - click Message button in the Graph group on the OutlookSpy ribbon, click "Query Parameters", check "$expand" checkbox, click on the button next to the edit box.
In your particular case, the query would most likely be
singleValueExtendedProperties($filter=id eq 'String {00020329-0000-0000-C000-000000000046} Name TTSyncID')

Related

get In-Reply-To value from InternetMessageHeader in outlook graph api

I'm trying to use the MS graph API to get the In-Reply-To message header without having to return the entire header (internetMessageHeaders). I already get several properties (such as bccRecipients, from, id) which are documented here
I've seen several SO questions asking this and they point to using SingleValueExtendedProperties/internetMessageHeaders with a $filter clause. I've tried this and it appears to only work with properties which are documented
This is what I've tried all give a 404 error (i've checked the the In-Reply-To header is present on the actual message)
https://graph.microsoft.com/v1.0/me/messages/MSG_ID?
$select=Subject,internetMessageId,from,id,bccRecipients,
SingleValueExtendedProperties&$expand=SingleValueExtendedProperties($filter=In-Reply-To eq 'String 0x007D')
https://graph.microsoft.com/v1.0/me/messages/MSG_ID?
$select=Subject,internetMessageId,from,id,bccRecipients,
internetMessageHeaders&$expand=SingleValueExtendedProperties($filter=In-Reply-To eq 'String 0x007D')
https://graph.microsoft.com/v1.0/me/messages/MSG_ID?
$select=Subject,internetMessageId,from,id,bccRecipients,
internetMessageHeaders&$expand=internetMessageHeaders($filter=In-Reply-To eq 'String 0x007D')
You need to request PR_IN_REPLY_TO_ID MAPI property (0x1042001F)
$expand=singleValueExtendedProperties($filter=id eq 'String 0x1042')

Searching Microsoft Graph api with spaces in the name

I'm using Microsoft Graph to do a search on the displayName for a substring of the name. The $search="displayName:MySearchTerm" format works perfect. But trying to search on the displayName with a space in the term doesn't seem to work as expected.
Using the sandbox application here
https://developer.microsoft.com/en-us/graph/graph-explorer?request=groups?$expand=members&method=GET&version=v1.0
If I use the following query format:
https://graph.microsoft.com/v1.0/groups?$search="displayName:Product vi"&$select=displayName&$orderBy=displayName
how can I get it to return only those records that have the term Product vi in the displayName field.
It shouldn't return any records in the sandbox because the term Product vi does not appear exactly in any part of the displayName but it currently returns the record "displayName": "Video Production"
I've tried the following without success:
$search="displayName:"Product vi""
$search="displayName:\"Product vi\""
$search="displayName:\\"Product vi\\""
$search="displayName:\\\"Product vi\\\""
$search="displayName:'Product vi'"
$search="displayName:\'Product vi\'"
The $filter format is no good to me as it doesn't search the middle of the displayName for the string.
How do I format the url to get the desired results if it is even possible?
The trick is to use comma instead of the space in $search clause.
https://graph.microsoft.com/v1.0/groups?$search="displayName:Product,vi"&$select=displayName&$orderBy=displayName
If $search clause contains "displayName:Product,vi" then Graph API will search on displayName for "Product vi"
It can require a special request header:
ConsistencyLevel: eventual
Try with %22
instead of
%20
good code...

Search for an event according to a specific value of a singleValueExtendedProperty

Situation:
We have an old application that is creating events in outlook (via MAPI). To identify the events the custom property 'CTOID' is set with a specific value by which the events can be found again.
For a newer application we would like to use the Graph API but the application should still be able to read/find the events created by the old application. So I created a test event with a specific CTOID and I can already use the graph client to get the mentioned event with the according property and its value (queryOptions is just some start-/enddate restrictions).
// Initialize the GraphServiceClient.
GraphServiceClient client = await m_MicrosoftGraphClient.GetGraphServiceClient();
// Load user events.
var request = client.Users[userId].CalendarView.Request(queryOptions).Expand("singleValueExtendedProperties($filter=id%20eq%20'Double%20{00020329-0000-0000-C000-000000000046}%20Name%20CTOID')");
var result = await request.GetAsync();
var calendarEvents = result.CurrentPage;
Result:
The event gets fetched correctly including the value for the CTOID property.
Problem:
I can "Expand" events so they contain the value for the CTOID property. But how do I find an event with a specific CTOID value? And specifically, how do I do this with the Graph client in C#?
According to the documentation and this Stackoverflow post, the following REST call should work:
GET /users/{id|userPrincipalName}/events?$filter=singleValueExtendedProperties/Any(ep: ep/id eq '{id_value}' and ep/value eq '{property_value}')
So I tried this in the online Graph Explorer:
https://graph.microsoft.com/v1.0/users/[MY_USER_ID]/events?$filter=singleValueExtendedProperties/Any(ep: ep/id eq 'Double {00020329-0000-0000-C000-000000000046} Name CTOID' and ep/value eq '229236')
But all I get as response is:
{
"error": {
"code": "ErrorInvalidUrlQueryFilter",
"message": "The filter expression for $filter does not match to a single extended property and a value restriction.",
"innerError": {
"date": "2020-08-03T12:44:05",
"request-id": "33e82c77-92ea-4865-a8d0-00cfc2f99154"
}
}
}
What am I doing wrong? I'm out of ideas and any help would be greatly appreciated.
(Also if you have any idea how to do this with the Graph client in C# and not just the bare REST call).
Additional Information:
Don't know if it's important, but the following permissions are set for our application:
In your filter you need to cast the value to a Double eg
https://graph.microsoft.com/v1.0/users/[MY_USER_ID]/events?$filter=singleValueExtendedProperties/Any(ep: ep/id eq 'Double {00020329-0000-0000-C000-000000000046} Name CTOID' and cast(ep/value, Edm.Double) eq 229236)
For anything other then a String in a filter you need to do this

OpenExtensions: Find and retrieve Events with a given extension

I'm looking to write events to a users calendar that correspond objects in my system. I also want the ability to update and/or delete those that change between runs of the process that updates the user's calendar.
To this end I'm using Open Extensions to write additional data onto the Calendar Events that I'm creating. This is working nicely and I can see the Extension data being written.
I can use a $filter to query for events that I have written to the user's calendar:
/v1.0/me/events?$filter=Extensions/any(f: f/id eq '{id}')
This works fine and I'm seeing the results I expect. It's worth noting that the id in this query works just fine with either the fully qualified form of Microsoft.OutlookServices.OpenTypeExtension.{extensionName} or just using the short form of {extensionName}
However I cannot get the events to return with the $expanded Extension. I've tried the examples from the docs but using this query it fails:
/me/events?$filter=Extensions/any(f: f/id eq '{id}')&$expand=Extensions($filter=id eq '{id}')
Like this:
{
"error": {
"code": "BadRequest",
"message": "Parsing Select and Expand failed.",
"innerError": {
"date": "2020-06-19T17:14:59",
"request-id": "d1125156-05a6-499a-b9a4-6c66e5ce377d"
}
}
}
I need the expanded Extension data to correlate the Calendar event back to the objects in my system to allow for updates or deletes as needed.
Does anyone know what might be happening or how to resolve this?
I got an answer through another question: Receiving 400s and 500s when attempting to get singleValueExtendedProperties
The issue is that the = symbol inside the $expand expression needs to be uriEncoded. The correct query to use is: /me/events?$filter=Extensions/any(f: f/id eq '{id}')&$expand=Extensions($filter%3Did eq '{id}')

Using OR in filters for Office 365 Service Communications API or filtering by multiple IDs

How can I filter by multiple IDs using the Office 365 Service Communications API?
I'm getting the current status using https://manage.office.com/api/v1.0/{tenent}/ServiceComms/CurrentStatus which gives me incident IDs. I'm trying to use those IDs to get the messages affiliated but the message endpoint /ServiceComms/Messages is not working well with the filters.
The documentation shows:
I've tried:
/ServiceComms/Messages?ID=CR555555,/ServiceComms/Messages?ID='CR555555', /ServiceComms/Messages?Id=CR555555,/ServiceComms/Messages?Id='CR555555' - Returns everything (doesn't filter)
/ServiceComms/Messages?$filter=ID eq 'CR555555' - Returns Error
/ServiceComms/Messages?$filter=Id eq 'CR555555' - Returns 1 result
/ServiceComms/Messages?$filter=Id eq 'CR555555' or Id eq 'CR555556' - Returns error
I was able to get an AND result using
$filter=MessageType eq Microsoft.Office365ServiceComms.ExposedContracts.MessageType'Incident' and EndTime ge 2019-07-25T00:00:00Z but OR always errors with the message "Filter {filter} is invalid. Expected '<Item> <operator> <Value>' pattern."
You need to use Microsoft.Office365ServiceComms.ExposedContracts.MessageType'Incident' as your MessageType.
A request to /Messages should return you a odata context at the top of the response. For example:
{
"#odata.context": "https://office365servicecomms-prod.cloudapp.net/api/v1.0/{{TenantID}}/$metadata#Messages",
...
}
If you query that, you receive the metadata along with the possible filters. I cannot give you an example as of today (2020-02-16) a query returns a 500 Internal Server Error. Microsoft is working on a fix. Maybe it works again by the time you read my reply.
Complete example:
https://manage.office.com/api/v1.0/{{TenantID}}/ServiceComms/Messages?$filter=MessageType eq Microsoft.Office365ServiceComms.ExposedContracts.MessageType'Incident' and LastUpdatedTime ge 2020-02-13T00:00:00.000Z
And yes, the ID filter must be written 'Id'. Microsofts documentation has a lot of wrong information in it.

Resources