OData of Outlook Event List cannot order by "Id" - c#

I tried to get a list of events from Microsoft Graph following this documentation.
I would like to get the list with order by lastModifiedDateTime and then id.
Here is the sample query:
var getResource = string.Format("/me/calendar/events/?$filter=lastModifiedDateTime ge {0}&$orderBy=lastModifiedDateTime, id", XmlConvert.ToString(updatedMin, XmlDateTimeSerializationMode.Utc));
However, when I executed it, it results an error:
{
"error": {
"code": "ErrorInvalidProperty",
"message": "The property 'Id' does not support filtering.",
"innerError": {
"request-id": "bb56a0d0-46f3-4b7c-80bd-043a0b3fd8b5",
"date": "2018-09-17T15:23:40"
}
}
}
In fact, I didn't set the Id within $filter, but instead, I set it as $orderby.
When I tried to exclude the Id from $orderby, it works. Here is the working query:
var getResource = string.Format("/me/calendar/events/?$filter=lastModifiedDateTime ge {0}&$orderBy=lastModifiedDateTime", XmlConvert.ToString(updatedMin, XmlDateTimeSerializationMode.Utc));
Anyone has an idea on how to order the list based on Id as well?

You cannot order by id, nor would it make any sense to do so. The id is a hashed combination of several properties (subject, path, etc.). As such, their value is neither orderable or human-readable.
This, for example, is an actual id value:
AAMkAGVmMDEzMTM4LTZmYWUtNDdkNC1hMDZiLTU1OGY5OTZhYmY4OABGAAAAAAAiQ8W967B7TKBjgx9rVEURBwAiIsqMbYjsT5e-T7KzowPTAAAAAAENAAAiIsqMbYjsT5e-T7KzowPTAACNM9xPAAA=
Also, I strongly recommend using the Microsoft Graph .NET Client rather than rolling your own. It will help reduce the learning curve and give you more readable code:
await graphClient.Me
.Calendar
.Events
.Request()
.Filter("lastModifiedDateTime ge {dateTime}")
.OrderBy("lastModifiedDateTime")
.GetAsync();

Related

How do I get the parent folder using the Google Drive API?

I'm trying to write a method that gets the parent folder of the folder whose Id is passed in. I have tried many different variations, most of which come from accepted answers here, but every one causes an exception.
For example, the following code...
public async Task<DriveFile> GetParentFolder(string folderId) {
FilesResource.ListRequest request = _service.Files.List();
request.Q = $"parents contains '{folderId}'";
request.Fields = "*";
FileList files = await request.ExecuteAsync();
return files.Files[0];
}
...throws the following exception...
Error: The service drive has thrown an exception: Google.GoogleApiException: Google.Apis.Requests.RequestError
Invalid Value [400]
Errors [
Message[Invalid Value] Location[q - parameter] Reason[invalid] Domain[global]
]
I have tried many values for the Q and Fields properties, but all result in the same exception.
I have other code working with the API, so it's not the basic service that's a problem, and I've used the API to get the Ids of some folders, so I know I'm passing in a valid value.
One of the problems is that v2 of the API had a Parents list, which looks like it does what I want, but this seems to be missing in v3.
Anyone able to help me? Thanks
Your going about it the wrong way you dont need to use file.list you already have the file id just use file.get.
Lets say i have the folder id here.
{
"kind": "drive#file",
"id": "1bzDkXlcND_yycIcbqwr1YYZ98-Yv7SG7",
"name": "Current Badges (2019-21)",
"mimeType": "application/vnd.google-apps.folder"
},
As you can see in this example i have the id and the mime type is a folder.
All i need to do is do a file.get
var request = _service.Files.Get("1bzDkXlcND_yycIcbqwr1YYZ98-Yv7SG7");
request.Fields = "parents";
var response = request.Execute();
The response will contain a filed called parents which is the parent of the folder.
As you can see if you already know the file id or in this case the folder id. Then you really just need to use file.get to get all the information about that id.
There's really no reason to use file.list.

Filtering Event Messages using Microsoft Graph REST API

I would like to query only Event Messages from Outlook Mail using the Microsoft GRAPH API. I could not find any information on this in the documentation for Microsoft Graph.
I have tried the following queries on the Graph Explorers, but none worked. It seems like Microsoft Graph does not support the IsOf (which filters the type of an object) filtering option. However, I have found that this feature is supported and documented for Azure GRAPH API.
https://graph.microsoft.com/v1.0/me/messages?$filter=isof('#microsoft.graph.eventMessage') eq true
https://graph.microsoft.com/v1.0/me/messages?$filter=isof('#microsoft.graph.eventMessage')
Does anyone know if the operation I tried to do is supported by the Microsoft Graph API? If not, is there anything else I can do to query only Event Messages?
As URL: Query string parameters states for the $filter parameter:
Indicates which entity types should be included in the response. Optional. The supported entity types are: User, Group and Contact. Only valid when resourceSet is “directoryObjects”; otherwise, resourceSet overrides the filter.
For example,
https://graph.windows.net/contoso.com/directoryObjects?api-version=2013-04-05&$filter=isof('Microsoft.WindowsAzure.ActiveDirectory.User')
For Microsoft Graph, I checked Use query parameters, but did not find any samples. Then, I used Graph Explorer to test this scenario as follows:
I assumed that this operation is not supported by Microsoft Graph API for now. You could add your feature request here. Or you could use the $select query parameter to return a set of properties. Details you could follow here.
The isof can be used with objects with an "#odata.type"
E.g. https://graph.microsoft.com/v1.0/deviceManagement/deviceConfigurations?$filter=isof('microsoft.graph.windowsUpdateForBusinessConfiguration')
returns
{
"#odata.context": "https://graph.microsoft.com/v1.0/$metadata#deviceManagement/deviceConfigurations",
"value": [
{
"#odata.type": "#microsoft.graph.windowsUpdateForBusinessConfiguration",
"id": "123123-1234-1234-1234-123456789123",
"lastModifiedDateTime": "2022-07-18T10:01:53.713763Z",
"createdDateTime": "2022-07-18T10:01:53.713763Z",
"description": "",
"displayName": "my Name",
...
{
]
}

SCIM Deserialization Issue in .NET

As a newcomer to the SCIM (System for Cross-domain Identity Management) standard, please excuse any ignorance as I'm on the learning curve trying to figure out how to make clean/simple requests to provision users, delete users and modifiy users.
I'm attempting to use C#/.NET to make HTTP REST requests for a user via SCIM, using the System.Net.Http.HttpClient
https://msdn.microsoft.com/en-us/library/system.net.http.httpclient(v=vs.110).aspx
I can do this successfully and get a JSON response from the server, however in order to easily read the response object and manipulate it, I want to deserialize it.. After much reading around trying to use things like JsonConvert, dynamic etc. I stumbled upon a Microsoft nuget library which seemed to hint at being useful. Sadly there don't appear to be any docs for it*
UPDATED:
One of the authors has updated the nuget page with a link to a blog post which goes some way to explaining usage.
Microsoft.SystemForCrossDomainIdentityManagement
https://www.nuget.org/packages/Microsoft.SystemForCrossDomainIdentityManagement/
The SCIM provider I'm attempting to get data from is Facebook, using the example they publish on their site for getting a user by email:
https://developers.facebook.com/docs/facebook-at-work/provisioning/scim-api#getuserbyemail
Here's a code sample in C# which attempts to get the user from the SCIM service and deserialize them. I'm finding that the queryResponse I get back is deserialized correctly as the properties are populated, however the Core1EnterpriseUser which is the first and only of the resource objects, has null/default properties.
var userName = "foo.bar#foobar.com";
var response = await client.GetAsync($"Users?filter=userName%20eq%20%22{userName}%22");
if (response.IsSuccessStatusCode)
{
var json = await response.Content.ReadAsStringAsync();
var jsonResponseProperties = await Task.Factory.StartNew(() => { return JsonConvert.DeserializeObject<Dictionary<string, object>>(json); });
var userFactory = new QueryResponseJsonDeserializingFactory<Core1EnterpriseUser>();
var queryResponse = userFactory.Create(jsonResponseProperties);
if (queryResponse.TotalResults == 1)
{
var user = queryResponse.Resources.First();
var id = user.Identifier; // this and other properties are null/false etc.
}
}
Here's a sample of the JSON that is returned by the service when I query it:
{
"schemas": [
"urn:scim:schemas:core:1.0"
],
"totalResults": 1,
"itemsPerPage": 10,
"startIndex": 1,
"Resources": [
{
"schemas": [
"urn:scim:schemas:core:1.0",
"urn:scim:schemas:extension:enterprise:1.0",
"urn:scim:schemas:extension:facebook:starttermdates:1.0",
"urn:scim:schemas:extension:facebook:suppressclaimemail:1.0"
],
"id": 180383108978226,
"userName": "foo.bar\u0040foobar.com",
"name": {
"formatted": "Foo Bar",
"familyName": "Bar",
"givenName": "Foo"
},
"title": "Vice President",
"active": true,
"emails": [
{
"primary": false,
"type": "work",
"value": "foo.bar\u0040foobar.com"
}
],
"urn:scim:schemas:extension:enterprise:1.0": {
"department": "IT"
},
"urn:scim:schemas:extension:facebook:starttermdates:1.0": {
"startDate": 0,
"termDate": 0
}
}
]
}
UPDATE:
I'm in dialog with one of the authors of the project and he kindly pointed me at this blog post:
http://blogs.technet.com/b/ad/archive/2015/11/23/azure-ad-helping-you-adding-scim-support-to-your-applications.aspx
He has also updated the nuget library which now includes support for v1 of SCIM, also pointing out that as the JSON data suggests the version used by Facebook is v1: "urn:scim:schemas:core:1.0" so now I can use Core1 rather than attempting to use Core2 classes (I've updated the question above to use Core1EnterpriseUser).
I'm still not able to get my response deserialized correcty at present and will update the question with more information as I have it.
Again, I don't have to use this library if it becomes apparent that it's not easily going to work, as I know the brief description on nuget suggests it was created for Azure AD.
However I'd appreciate any advice on how this type of thing could/should be done as I'm sure there must be a lot of people out there using SCIM - how do you parse your responses/generate your requests such that you have actual objects? Can you automatically parse responses for schemas in order to augment the object with the correct properties?
I was up late last night hand crafting some model classes to handle the response objects - which I do seem to have working. If I can't get the nuget library working (the preferred option) then I'll have to go with my own. :/
Thanks again
peteski
Although I'm still none the wiser about best practices with SCIM, I've managed to get the code working now - with massive thanks to one of the nuget library's authors Craig McMurtry at Microsoft!
There were a few things to iron out along the way, such as the nuget package being updated to include the previous support for older v1 SCIM objects. But here's a snippet of what worked based on the example in my question, but it turned out to be using the Newtonsoft serializer. :(
In the code above the line:
var jsonResponseProperties = await Task.Factory.StartNew(() => { return JsonConvert.DeserializeObject<Dictionary<string, object>>(json); });
Was replaced with:
var jsonResponseProperties = new JavaScriptSerializer().Deserialize<Dictionary<string, object>>(json);
Et voilà! My object's properties are now deserializing...

How to filter Facebook pages by CREATE_CONTENT permission?

I have the following Graph API call: me/accounts?fields=access_token,name,id,perms that I use to get the page tokens from the user.
Now I would like to filter this by perms="CREATE_CONTENT". How can I filter this Graph API call?
I'm using the C# Facebook.net SDK. Currently I use this code:
client.Post("me/accounts", new { fields = "access_token,name,id,perms" });
Opening caveat: I do not know C#, but I regularly work with the Facebook in other programming languages.
Facebook has a number of "Publish Permissions" as part of its Extended Permissions. I'm assuming you're already requesting one or more of these permissions from your users. (I don't see a create_content listed; that's the only reason I mention it.) Let's say, for example, you requested the create_event permission from your users.
Try accumulating the Facebook User IDs into a list, and then issuing a FQL query using the Facebook SDK client for the permission(s) you're interested in:
List<int> facebookUserIds = new List<int>(1, 2, 3);
var query = string.Format("SELECT uid, create_event FROM permissions WHERE uid IN ({})", string.Join(",", facebookUserIds));
dynamic parameters = new ExpandoObject();
parameters.q = query;
dynamic results = client.Get("/fql", parameters);
The response you receive will have properties like this (here, in JSON format):
{
"data": [
{
"uid": 1,
"create_event": 1
},
{
"uid": 2,
"create_event": 0
}
{
"uid": 3,
"create_event": 0
}
]
}
Of course, 0 means permission denied, and 1 means permission granted for the App ID you're using to authenticate with the Facebook API.
Note: Users will only be returned in the response if they've previously authenticated your app (of the most basic level of permissions); but this shouldn't be an issue.
You can't directly filter this in the API, but it would be quite easy to do from c#- you're getting an ICollection from the Facebook.JSONObject response, so you can just use linq to filter it - Filtering collections in C# has a pretty good explanation of how to achieve this.

Why this api shows error message "Unknown fields: gender"?

I am using a graph api for facebook app. I am using this api
https://graph.facebook.com/<friendlist_id>/members?fields=id,name,gender&access_token=<access_token>
But it shows me error,
{
"error": {
"message": "(#100) Unknown fields: gender.",
"type": "OAuthException",
"code": 100
}
}
When I remove "gender" from the api, it works properly. So, why this api shows me this error. How to get gender of a user in this api?
Because according to the Friend List documentation the members connection is An array of objects containing friend id and name fields. - those are the only two fields in
the structure - you'll need to fetch any other data you need about those IDs in another call
(Though most apps would probably already have the result of /me/friends cached so this should be pretty fast)
You wouldn't be able to pull the gender in one go as Igy said, so a way to do it in FQL would be
SELECT uid, sex FROM user WHERE uid IN (SELECT uid, flid FROM friendlist_member WHERE flid = <friendlist_id>)

Categories