I try to use Graph API SDK to query a file in a SharePoint site
var site = await graphClient.Sites["myDomain"]
.SiteWithPath("relativePath").Request()
.GetAsync().ConfigureAwait(false);
var drive = await graphClient.Sites["myDomain]
.SiteWithPath("relativePath").Lists["mylib"].Drive
.Request().GetAsync().ConfigureAwait(false);
var file = await graphClient.Sites[site.Id]
.Drives[drive.Id].Root.ItemWithPath("/folder1").Children["myfile.txt"]
.Request().GetAsync().ConfigureAwait(false);
This is working and I get the file.
I try to combine the three steps into one,
var file = await graphClient.Sites["myDomain"]
.SiteWithPath("relativePath").Lists["mylib"].Drive
.Root.ItemWithPath("/folder1").Children["myfile.txt"]
.Request().GetAsync().ConfigureAwait(false);
But it gives Bad Request error. What's wrong? What is the best way to do this?
The navigation you are using is not accepted by Graph.
As per the get files docs, you need the site-id.
# Valid
GET /sites/mydomain.sharepoint.com:/relativePath/lists/mylib/drive
# Invalid addition to above url
GET /sites/mydomain.sharepoint.com:/relativePath/lists/mylib/drive/root:/myfile.txt:
If you don't have the site id, you can expand the list relationship in the get list drive call and use the site-id to request for the file. This will be two requests instead.
var drive = await graphServiceClient
.Sites["mydomain.sharepoint.com"]
.SiteWithPath(relativePath)
.Lists["mylib"]
.Drive
.Request()
.Expand("list")
.GetAsync()
.ConfigureAwait(false);
var file = await graphServiceClient
.Sites[drive.List.ParentReference.SiteId]
.Drives[drive.Id]
.Root.ItemWithPath("/Folder 1")
.Children["myfile.txt"]
.Request().GetAsync().ConfigureAwait(false);
Related
I am trying to access Teams-Ressourcec via the Microsoft graph-API. I seem to hit a wall with that. The app has the required permissions (as listed in MS documentation)
Queries I've tried:
A simple GET:
string querystring = "api-version=1.6";
var uri = "https://graph.windows.net/contoso.onmicrosoft.com/teams/" + TeamID+ "/channels?" + querystring;
Console.WriteLine(uri);
HTTPClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", result);
var GetResult = await HTTPClient.GetAsync(uri);
This one works with delegated permissions in Graph Explorer (v1.0) however it uses delegate user permissions, and not app permissions.
POST for migration team reation:
string querystring = "api-version=1.6";
var uri = "https://graph.windows.net/contoso.onmicrosoft.com/teams?" + querystring;
HTTPClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);
HttpRequestMessage Content = new HttpRequestMessage();
Content.Content = new StringContent("{ \"#microsoft.graph.teamCreationMode\": \"migration\", \"template#odata.bind\": \"https://graph.microsoft.com/v1.0/teamsTemplates('standard')\", \"displayName\": \"My Sample Migration Team\", \"description\": \"\", \"createdDateTime\": \"2020-03-14T11:22:17.043Z\" }", Encoding.UTF8, "application/json");
var GetResult = await HTTPClient.PostAsync(uri, Content.Content);
For both of those, I receive "Resource not found for the segment 'teams'.
Has anybody seen That? How can I acces\work with Teams resources via Graph API?
When you call https://graph.windows.net, this is Azure AD Graph which is deprecated and will be decommissioned from June 30th 2022.
I recommend you switch over to use Microsoft Graph which you call https://graph.microsoft.com/version. See Graph Explorer to get started.
Check List Channels on how to list teams channels using MS Graph.
I can see how to trigger the calculation of a spreadsheet using Microsoft Graph API here...
https://learn.microsoft.com/en-us/graph/api/workbookapplication-calculate?view=graph-rest-1.0&tabs=http
But, when I pull the results from the calculations they don't seem to be updated. However, I pull a second or third time, it is usually updated.
I assume this means that calculation hasn't finished b/c of the size of the file or complexity of the calcs.
However, being asynchronous, I'm not finding any way to check to see when the calculations have finished.
Any idea how to do this?
UPDATE 1:
This is the code I'm (now) using to create the session (per #UJJAVAL123-MSFT)
var persistChanges = false;
var wrkbk = await graphClient.Me.Drive.Items[strItemId].Workbook
.CreateSession(persistChanges)
.Request()
.PostAsync();
This will give me a value for 'id' like this...
cluster=US5&session=15.SN3PEPF000074ED1.A82.1.V24.7737Nwad4oPuVafaO%2fpAkiay14.5.en-US5.en-US26.10037ffe965d2cf2-Unlimited1.A1.N16.16.0.12904.3505114.5.en-US5.en-US1.V1.N0.1.A&usid=1b230e8f-3bd0-cdaa-2da6-47db74154075
I'm not exactly sure how/where to use this, or whether I use the entire thing (it looks like a query string) or if I'm supposed to parse and pull out one of the values...
cluster=US5
session=15.SN3PEPF000074ED1.A82.1.V24.xxxxxxxxxxxxxxxxx%2fpAkiay14.5.en-US5.en-US26.10037ffe965d2cf2-Unlimited1.A1.N16.16.0.12904.3505114.5.en-US5.en-US1.V1.N0.1.A
usid=1b230e8f-3bd0-cdaa-2da6-xxxxxxxxxxxx
and this is the code i'm using to trigger the calculation, but not sure how to connect the two...
var calculationType = "FullRebuild";
await graphClient.Me.Drive.Items[strItemId].Workbook.Application
.Calculate(calculationType)
.Request()
.PostAsync();
Also, I'm seeing that it is possible to create, refresh and close a session, but not entirely sure how to check on a specific async process inside that session.
Here is the code I'm using to check a specific range for a value, not sure where we pass the session-id here either...
var result = await graphClient.Me.Drive.Items[strItemId].Workbook.Worksheets[strSheetName]
.Range(strRangeName)
.Request()
.GetAsync();
UPDATE 2:
I can run an API call (presumably) in the same session successfully by passing the workbook-session-id (which is the ENTIRE string shown above) and I get the expected 204 No Content response. However, it is not clear from the c# Code Snippet in the Microsoft Graph Explorer how to pass the workbook-session-id in the request.
Here is the code it provides...
GraphServiceClient graphClient = new GraphServiceClient( authProvider );
await graphClient.Me.Drive.Items["{item-id}"].Workbook.Application
.Calculate(null)
.Request()
.PostAsync();
So the question remains, how can I do a PostAsync or GetAsync and reference the workbook-session-id?
This code does NOT give me an error...
await graphClient.Me.Drive.Items[strItemId].Workbook.Application
.Calculate(calculationType)
.Request()
.Header("workbook-session-id",wrkbk.Id)
.PostAsync();
So now, the question is WHEN do I get the workbook-session-id? Do I get it when I initially open the workbook and then pass it to every call?
You should create a session and pass the session Id with each request. The presence of a
session Id in the requests ensures that you are using the Excel API in the most efficient
way possible.
Check here for API call to get a session
So after a decent amount of testing, i figured it out.
The answer is that you use the CreateSession method (https://learn.microsoft.com/en-us/graph/api/workbook-createsession?view=graph-rest-1.0&tabs=http) to get the workbook info, and you set the persistChanges setting, then you get back info about the workbook session.
Like this...
using Microsoft.Graph;
// strItemId = the id from the microsoft graph api of the item
// strUserId = the id of the user from the microsoft graph api (note: must have permissions set correctly)
public static async Task<WorkbookSessionInfo> GetWorkbookSessionId(string strItemId, string strUserId)
{
// true = you can see changes in the workbook
// false = don't update the workbook, just do calculations
var persistChanges = true;
try
{
var wrkbk = await graphClient.Users[strUserId].Drive.Items[strItemId].Workbook
.CreateSession(persistChanges)
.Request()
.PostAsync();
var result = wrkbk;
return result;
}
catch (Exception ex)
{
Console.WriteLine($"Error getting items: {ex.Message}");
return null;
}
}
And you are returned a WorkbookSessionInfo object, which includes the SessionId for use in subsequent calls. This way, it keeps all your calls in the same session!
https://learn.microsoft.com/en-us/graph/api/resources/workbooksessioninfo?view=graph-rest-1.0
I use the MS Graph API to upload data to OneDrive.
I have deleted all data on OneDrive, but when I use the :
var search = await graphClient.Users[user.Id].Drive.Root
.Search("")
.Request()
.GetAsync();
foreach (var item in search)
{
Console.WriteLine(item.Name);
}
I get data displayed even though my OneDrive is empty, why ?
I use:
.Net 4.7.2,
Visual Studio
The solution is:
If I use this code:
var search = await graphClient.Users[user.Id].Drive.Root
.Search("")
.Request()
.GetAsync();
He's searching through the index.
Data can also be displayed there although it is no longer available.
Therefore, data that is no longer available on OneDrive is also displayed.
Do not use the search function.
A rather simple ask but I'm having trouble converting my basic httpClient method of querying the Graph into the SDK method. I was using the following and it works fine:
var filter = "IT";
var response = await httpClient.GetAsync($"{webOptions.GraphApiUrl}/beta/groups?$filter=startswith(displayName, '{filter}')&$select=id,displayName");
...now I'm attempting to filter using the SDK as follows:
var groups = await graphServiceClient.Groups
.Request()
.Filter($"displayName startswith {filter}")
.Select("id, displayName")
.GetAsync();
I've also tried .Filter($"startswith("displayName", {filter})) and other variants.
I'm getting an invalid filter clause error. Any ideas?
Apparently it occurs since the provided filter expression for Filter method is invalid, it could be validated like this:
var message = graphServiceClient.Groups
.Request()
.Filter($"displayName startswith '{filter}'")
.Select("id, displayName").GetHttpRequestMessage();
The generated message.RequestUri will return the following value:
https://graph.microsoft.com/v1.0/groups?$filter=displayName startswith '{filter}'&$select=id, displayName}
A valid filter expression needs to be specified like this:
.Filter($"startswith(displayName, '{filter}')")
In case if you want to switch to beta version for GraphServiceClient class, it could be specified like this:
graphServiceClient.BaseUrl = "https://graph.microsoft.com/beta";
What api.onedrive.com endpoints can be used for reading, deleting and creating comments of documents stored in OneDrive?
var docId = "C382F44F3E2D3362!392363";
using (var http = new HttpClient()) {
var json = await http.GetStringAsync($"https://api.onedrive.com/v1.0/???{docId}???/comments");
var comments = JObject.Parse(json);
...
}
I need to rewrite an app which use Live SDK to manipulate OneDrive comments. Live SDK is deprecated now. I need an API which is currently supported.
OneDrive is a cloud storage system, it doesn't support directly editing the files stored on it