Reputation: 11871
I am using Microsoft Graph API and I am creating a folder like so:
var driveItem = new DriveItem
{
Name = Customer_Name.Text + Customer_LName.Text,
Folder = new Folder
{
},
AdditionalData = new Dictionary<string, object>()
{
{"@microsoft.graph.conflictBehavior","rename"}
}
};
var newFolder = await App.GraphClient
.Me
.Drive
.Items["id-of-folder-I-am-putting-this-into"]
.Children
.Request()
.AddAsync(driveItem);
My question is how do I check if this folder exists and if it does get the id of the folder?
Upvotes: 12
Views: 10392
Reputation: 555
My implementation uses the application level access to the graph api.
Create a drive item structure with children to represent your file tree and then traverse it alongside the actual graph api responses:
public class DriveItem
{
public string ItemID { get; set; }
public string Name { get; set; }
public string URL { get; set; }
public List<DriveItem> Children { get; set; }
}
public async Task<bool> DirectoryExists(DriveItemRequest request)
{
if (!string.IsNullOrEmpty(request.SiteID) &&
!string.IsNullOrEmpty(request.DriveID) &&
request.Root != null)
{
var currentFolder = await _client.Sites[request.SiteID].Drives[request.DriveID]
.Root.Children.Request().Filter($"name eq '{request.Root.Name}'").GetAsync();
if (currentFolder.Count > 0)
{
var currentItem = request.Root;
while (currentFolder.Count > 0 && currentItem.Children != null)
{
// navigate to child
currentItem = currentItem.Children[0];
// traverse folder structure
currentFolder = await _client.Sites[request.SiteID].Drives[request.DriveID]
.Items[currentFolder[0].Id].Children.Request()
.Filter($"name eq '{currentItem.Name}'").GetAsync();
}
return currentFolder.Count > 0 ? true : false;
}
}
return false;
}
Upvotes: 0
Reputation: 438
Few Microsoft Graph useful API's to search for specific folder into drive:
Check folder with name on root level of drive:
Method: GET
Required Header:
Authorization: Bearer <access_token>
API URL:
https://graph.microsoft.com/v1.0/drives/<your-drive-id>/root:/<folder_name_to_be_search>
Check folder with name exist inside any parent folder on root level:
Method: GET
Required Header:
Authorization: Bearer <access_token>
API URL:
https://graph.microsoft.com/v1.0/drives/<your-drive-id>/items/<parent-folder-id>:/<folder_name_to_be_search>
API to get list of all drive childrens:
Method: GET
Required Header:
Authorization: Bearer <access_token>
API URL:
https://graph.microsoft.com/v1.0/drive/root/children
API to get children items inside parent folder in drive:
Method: GET
Required Header:
Authorization: Bearer <access_token>
API URL:
https://graph.microsoft.com/v1.0/drives/<your-drive-id>/items/<parent-folder-id>/children
Upvotes: 0
Reputation: 59338
A query based approach could be considered in this regard. Since by design DriveItem.name
property is unique within a folder, the following query demonstrates how to filter driveItem
by name in order to determine if drive item exist:
https://graph.microsoft.com/v1.0/me/drive/items/{parent-item-id}/children?$filter=name eq '{folder-name}'
which could be represented in C# like this:
var items = await graphClient
.Me
.Drive
.Items[parentFolderId]
.Children
.Request()
.Filter($"name eq '{folderName}'")
.GetAsync();
Given the provided endpoint the flow could consist of the following steps:
Example
Here is a updated example
//1.ensure drive item already exists (filtering by name)
var items = await graphClient
.Me
.Drive
.Items[parentFolderId]
.Children
.Request()
.Filter($"name eq '{folderName}'")
.GetAsync();
if (items.Count > 0) //found existing item (folder facet)
{
Console.WriteLine(items[0].Id); //<- gives an existing DriveItem Id (folder facet)
}
else
{
//2. create a folder facet
var driveItem = new DriveItem
{
Name = folderName,
Folder = new Folder
{
},
AdditionalData = new Dictionary<string, object>()
{
{"@microsoft.graph.conflictBehavior","rename"}
}
};
var newFolder = await graphClient
.Me
.Drive
.Items[parentFolderId]
.Children
.Request()
.AddAsync(driveItem);
}
Upvotes: 4
Reputation: 3609
To get the folder with the folder name:
call graph api Reference1 Reference2: /me/drive/items/{item-id}:/path/to/file
i.e. /drive/items/id-of-folder-I-am-putting-this-into:/{folderName}
If the folder exists it returns a driveItem Response, which has the id
If the folder doesn't exist, it returns a 404 (NotFound)
Now, while creating a folder, if the folder already exists, in order to fail the call, try setting additional data as follows Reference:
AdditionalData = new Dictionary<string, object>
{
{ "@microsoft.graph.conflictBehavior", "fail" }
}
Upvotes: 6
Reputation: 14577
Graph API provides a search facility, that you could utilise to find out if an item exists. You have either an option of running the search first and then creating an item if nothing was found, or you could do as @Matt.G suggests and play around nameAlreadyExists
exception:
var driveItem = new DriveItem
{
Name = Customer_Name.Text + Customer_LName.Text,
Folder = new Folder
{
},
AdditionalData = new Dictionary<string, object>()
{
{"@microsoft.graph.conflictBehavior","fail"}
}
};
try
{
driveItem = await graphserviceClient
.Me
.Drive.Root.Children
.Items["id-of-folder-I-am-putting-this-into"]
.Children
.Request()
.AddAsync(driveItem);
}
catch (ServiceException exception)
{
if (exception.StatusCode == HttpStatusCode.Conflict && exception.Error.Code == "nameAlreadyExists")
{
var newFolder = await graphserviceClient
.Me
.Drive.Root.Children
.Items["id-of-folder-I-am-putting-this-into"]
.Search(driveItem.Name) // the API lets us run searches https://learn.microsoft.com/en-us/graph/api/driveitem-search?view=graph-rest-1.0&tabs=csharp
.Request()
.GetAsync();
// since the search is likely to return more results we should filter it further
driveItem = newFolder.FirstOrDefault(f => f.Folder != null && f.Name == driveItem.Name); // Just to ensure we're finding a folder, not a file with this name
Console.WriteLine(driveItem?.Id); // your ID here
}
else
{
Console.WriteLine("Other ServiceException");
throw;// handle this
}
}
The query text used to search for items. Values may be matched across several fields including filename, metadata, and file content.
you can play with search query and do things like filename=<yourName>
or potentially examine file types (which i guess is not going to help in your particular case, but I'd mention it for completeness sake)
Upvotes: 5
Reputation: 627
Issue a search request on the container.
var existingItems = await graphServiceClient.Me.Drive
.Items["id-of-folder-I-am-putting-this-into"]
.Search("search")
.Request().GetAsync();
You must then iterate the existingItems
collection (possible including multiple pages) to determine if the item exists.
You don't specify the criteria for determining if an item exists. Assuming you mean by name, you could:
var exists = existingItems.CurrentPage
.Any(i => i.Name.Equals(Customer_Name.Text + Customer_LName.Text);
Upvotes: 1
Reputation: 49
You can get the ID of the folder by calling this: https://graph.microsoft.com/v1.0/me/drive/root/children
. It'll give you all of the items in the drive. You can use the name or another property to filter your results to get the folder ID if you don't already have it
public static bool isPropertyExist (dynamic d)
{
try {
string check = d.folder.childCount;
return true;
} catch {
return false;
}
}
var newFolder = await {https://graph.microsoft.com/v1.0/me/drive/items/{itemID}}
if (isPropertyExist(newFolder))
{
//Your code goes here.
}
If the type of item in the drive is a folder it will get a folder
property. You can check if this property exists and if it does run your code to add the item.
Upvotes: 0