Filter Microsoft Graph API - microsoft-graph-api

I have a small question related with the Microsoft Graph API, regarding specific functions like filter/search. I use the 'users' endpoint and what I want is to be able to combine the basic filter function (e.g.: startsWith(displayName,Name)) that is set via the query params of the request, with a 'Not Equal' function.
What I tried so far looks something like this:
https://graph.microsoft.com/v1.0/users?$filter=startswith(displayName,'Surname%20FirstName')%20ne%20'Specific%20Name'
As an exception I get back:
Request_UnsupportedQuery
Does this mean that the specific endpoint does not support Not Equal function or my request does not conform with what the API expects?
Here is a small example where I found the search function used as I said, but for another end point.

From the documentation:
Note: The following $filter operators are not supported for Azure AD resources: ne, gt, ge, lt, le, and not. The contains string operator is currently not supported on any Microsoft Graph resources.

Related

How to get proper results for these queries?

Need to execute and return 1st order detail alone for each order. Below doesn't work
https://services.odata.org/Experimental/Northwind/Northwind.svc/Customers?$expand=Orders($expand=Order_Details;$top=1)
Need to filter records based on order id. Below doesn't work and throws "Term 'Orders($expand=Order_Details)$filter=OrderID eq '10643'' is not valid in a $select or $expand expression"
https://services.odata.org/Experimental/Northwind/Northwind.svc/Customers?$expand=Orders($expand=Order_Details)$filter=OrderID eq '10643'
Invalid but returned results
https://services.odata.org/Experimental/Northwind/Northwind.svc/Regions?expand=Order_Details
https://services.odata.org/Experimental/Northwind/Northwind.svc/Regions?expand=Territories
Not Returning Childrens
https://services.odata.org/Experimental/Northwind/Northwind.svc/Products?&expand=Suppliers
https://services.odata.org/Experimental/Northwind/Northwind.svc/Regions?&expand=Territories
https://services.odata.org/Experimental/Northwind is no longer 'Best Practise'
It's a bold statement, but this question proves that many advanced query features have not been fully or properly implemented in the published service.
While many developers may use it to practise OData query concepts, given that the OData implementation is largely up to the developers and the version of the packages they use, it is probably a of more commercial value if you query against a live or a dev implementation of the actual service that you want to query.
The following is an analysis of OPs queries and how to achieve the desired response according the the OData-V4 specification and verified against a deployed API that utilises the following NuGet packages:
Microsoft.AspNet.OData v7.3.0
Microsoft.OData.Core v7.6.2
The actual API that I used for testing is proprietary and cannot be published here.
According to the spec, you have to move the $top specifier to the Order_Details expansion.
https://services.odata.org/Experimental/Northwind/Northwind.svc/Customers?
$expand=Orders($expand=Order_Details($top=1))
However:
https://services.odata.org/Experimental/Northwind does not correctly implement $top query option within expansion as defined in 5.1.3 System Query Option $expand
Query options can be applied to an expanded navigation property by appending a semicolon-separated list of query options, enclosed in parentheses, to the navigation property name. Allowed system query options are $filter, $select, $orderby, $skip, $top, $count, $search, and $expand.
$top is however supported in the ODataLib v7+ (.Net) implementation of OData v4. So the syntax is correct, but you should check with your API developers for their opinion if your queries with this syntax do not work.
NOTE: When using $top you should also use $orderbyto ensure that the query results are reliable and reproducable:
https://services.odata.org/Experimental/Northwind/Northwind.svc/Customers?
$expand=Orders($expand=Order_Details($orderby=ProductID;$top=1))
To apply multiple query options within an expansion, you must separate then with a semi-colon: ;. However that alone will not prevent other customer records from being returned, so you must also add a root level filter as well, which is complicated by the fact that Orders is a collection. We can use the any function to only return customers that have an order with the specified Id:
Also note that OrderID is numeric, so do not wrap comparison values in quotes
https://services.odata.org/Experimental/Northwind/Northwind.svc/Customers?
$expand=Orders($expand=Order_Details;$filter=OrderID eq 10643)
&$filter=Orders/any(o:o/OrderID eq 10643)
this can be further simplified using parameter alias:
https://services.odata.org/Experimental/Northwind/Northwind.svc/Customers?
$expand=Orders($expand=Order_Details;$filter=OrderID eq #orderId)
&$filter=Orders/any(o:o/OrderID eq #orderId)
&#orderId='10643'
However:
https://services.odata.org/Experimental/Northwind does not correctly implement parameter aliases so you cannot verify the alias syntax against this service.
Also note
that experimental service is not correctly applying the filter to either the root elements or the navigation collection, the syntax shown here does however work against the .Net ODataLib implementations of OData v4.
The reason that your $expand is not working is that you have left off the $ from the parameter name. The OData query interpreter only identifies query options are parameters that start with $.
Eitherway, according to the https://services.odata.org/Experimental/Northwind/Northwind.svc/$metadata#Regions, there is no Order_Details navigation property to $expand on:
<EntitySet Name="Regions" EntityType="NorthwindModel.Region">
<NavigationPropertyBinding Path="Territories" Target="Territories" />
</EntitySet>
So when you try again with the correct syntax:
https://services.odata.org/Experimental/Northwind/Northwind.svc/Regions?$expand=Order_Details
you get the expected message:
Could not find a property named 'OrderID' on type 'NorthwindModel.Region'
The second attempt will work if you put the correct $ in there for the $expand query option:
https://services.odata.org/Experimental/Northwind/Northwind.svc/Regions?$expand=Territories
The OData query parser only looks for the expected query options with the $ prefix, this allows your API logic to still process other non-OData parameters as you see fit to do so. The other parameters therefor are still HTTP Url compliant parameters, the implementation at odata.org doesn't know what to do with them and they are simply ignored.
This is just another variation on the same issue with 3, the $ is missing. (I suspect that this URL was meant to be in 3: https://services.odata.org/Experimental/Northwind/Northwind.svc/Products?$expand=Suppliers)
So while https://services.odata.org/Experimental/Northwind is not 100% reliable, neither are the .Net ODataLib, SAP or MS Dynamics implementations. The spec is evolving and there are many query techniques that are not fully implemented in probably any providers at this stage.
Simply be mindful of this fact and when you run into issues using an API, the first point of contact should be the developers or the community that are supporting that particular API, it will be up to the developers what techniques and packages they use and at the end of the day to what extent they support the protocol as it is specified.

C# MsGraph-SDK: Send a BatchRequest to get manager links using Microsoft Graph SDK

First of all please share if there is any MSGraph SDK official documentation anywhere that I can use for reference.
I have a scenario, where I want to query all manager and member links from AAD without providing the user and group objectID respectively. This is currently supported in DQ channel, i.e. I can do something like this using MsGraphSDK:
MsGraphClient.Users.Delta().Request().Select("manager")
OR
MsGraphClient.Groups.Delta().Request().Select("members")
I don't want to use DQ for initial-sync due to performance problems, and other issues.
My fallback option is to query through Graph directly, so I want to do something like the following, but this doesn't return any result:
MsGraphClient.Users.Request().Select("manager")
OR
MsGraphClient.Groups.Request().Select("members")
It looks like this isn't even supported currently at the lower (AADGraph) layer. Please correct me if I am wrong, and provide a solution if any!
So my fallback approach is to pull all the user and group aadObjectIds, and explicitly query the manager and member links respectively.
In my case, there can potentially be 500K User-Objects in AAD, and I want to avoid making 500K separate GetManager calls to AAD. Instead, I want to batch the Graph requests as much as possible.
I wasn't able to find much help from the Internet on sending Batch requests through SDK.
Here's what I am doing:
I have this BatchRequestContent:
var batchRequestContent = new BatchRequestContent();
foreach (string aadObjectId in aadObjectIds)
{
batchRequestContent.AddBatchRequestStep(new BatchRequestStep(aadObjectId, Client.Users[aadObjectId].Manager.Request().GetHttpRequestMessage()));
}
and I am trying to send a BatchRequest through GraphSDK with this content to get a BatchResponse. Is this currently supported in SDK? If yes, then what's the procedure? Any documentation or example? How to read the batch-response back? Finally, is there any limit for the # of requests in a batch?
Thanks,
Here is a related post: $expand=manager does not expand manager
$expand is currently not supported on the manager and directReports relationships in the v1.0 endpoint. It is support in the beta endpoint but
the API returns way to much throw away information: https://graph.microsoft.com/beta/users?$expand=manager
The client library partially supports Batch at this time although we have a couple of pull requests to provide better support
with the next release (PR 1 and 2).
To use batch with the current library and your authenticated client, you'll do something like this:
var authProv = MsGraphClient.AuthenticationProvider;
var httpClient = GraphClientFactory.Create(authProv);
// Send batch request with BatchRequestContent.
HttpResponseMessage response = await httpClient.PostAsync("https://graph.microsoft.com/v1.0/$batch", batchRequestContent);
// Handle http responses using BatchResponseContent.
BatchResponseContent batchResponseContent = new BatchResponseContent(response);

How to search users in Microsoft Graph SDK with C#?

In my C# application, I am using Microsoft Graph SDK with Azure AD implementation.
Please suggest me how to search users in my organisations (global contacts) based on search parameters .
For example , if "Raj" is the search parameter, I should be able to get all users with their name contains "Raj" or email address contains "Raj".
I found this method to get all users - "graphClient.Users.Request().GetAsync();". but, with this method limited response, I am not getting what exactly I want to search.
Thanks,
Shashidhar
Adding to the previous answer: to accomplish this through the Graph C# SDK, use the Filter() method:
graphClient.Users.Request().Filter("startsWith(displayName, 'k')").GetAsync()
You can use other methods on the request to customize the request, e.g. Select(), etc.
According to your description, I assume you want to search the users by using the search parameters.
Based on this document, we can currently search only message and person collections.
And I have tried the filter query parameter, the parameter is currently not supported the contains operator from this document. So if you want to search the user with name or the email address, we can use the startswith operator only.Like this:
https://graph.microsoft.com/v1.0/users?$filter=startswith(displayName,'k') or startswith(mail,'k')
It will find the user's diplayName or mail which is start with the k

Microsoft Graph API $filter=substringof() not working

I try the API as below, but the response message is "Invalid filter clause".
GET https://graph.microsoft.com/v1.0/me/joinedgroups?$filter=substringof(name,'WIO')
Did I miss anything?
The API is OData V4 compliant, which does not have substringof function (reference).
Also, "me/joinedGroups" is not a supported query. Please use "me/memberOf/$/microsoft.graph.group?$filter=groupTypes/any(a:a eq 'unified')" to find all unified groups the user is a member of. Additional filter clauses in above query is not supported at the moment.
You can try using '$search' instead if applicable:
https://graph.microsoft.com/v1.0/users?ConsistencyLevel=eventual&$search="givenName:Jo" OR "surname:smith"
https://graph.microsoft.com/v1.0/groups?$top=2&ConsistencyLevel=eventual&$search="displayName:Group Name"

Does OData 2.0 support "contains" in the filter

I can see in the Basic Tutorial section of the odata website that you can perfom a contains search using a filter
GET serviceRoot/Airports?$filter=contains(Location/Address, 'San Francisco')
The API I am using refused this when I tried to use it. The API I am accessing is OData 2.0.
So I wanted to know if OData 2.0 supports the contains filter but couldn't find a list anywhere documenting the filters you could use e.g. startsWith, endsWith, contains
My research led me to the only answer I could find which was to use substringof instead of contains. This is the end of the url call from the actual API I am working on. This results in searching for Items filtered by Description containing "69":
/logistics/Items?$filter=substringof('69',%20Description)%20eq%20true

Resources