C# Google Drive SDK Why I cannot search item by its name? - c#

I have strange problem.
I have some folders in my Google Drive, and one is named myFolder. That folder has visibility option set to Anyone with the link.
I want to get that folder ID. To do so, I have the following code
ChildrenResource.ListRequest request = Google_DriveService.Children.List("root");
request.Q = "mimeType='application/vnd.google-apps.folder' and title='myFolder' and trashed=false";
try
{
ChildList children = request.Fetch();
return children.Items;
}
catch (Exception e)
{
throw e;
}
which throws error 500. But, if I change the query to "mimeType='application/vnd.google-apps.folder' and trashed=false"; I get the list of the folders, but there is no posibility to know which folder in that list is the one that I want.
So
1) why I get that error 500 if I pass the folder name inside that query ?
2) How to get folder details (e.g. its name) if I have ID ?
EDIT
OK, I've changed the code as you guys suggested, now I don't get the error, but the folder is still not found. It is placed in the root folder.
var request = Google_DriveService.Files.List();
request.Q = "mimeType='application/vnd.google-apps.folder' and title='myFolder' and trashed=false";
var children = request.Fetch();
return children.Items.Count > 0 ? children.Items.First().Id : null;

1 . Probably a Bug. Try running your query from https://developers.google.com/drive/v2/reference/files/list#try-it to confirm
What scope are you using? If drive.file, try switching to drive
2 . In the returned JSON, look for 'title'. If you need to be sure it's the right file, you maybe need to check the parent id vs the parent id of myfolder.

I think you need to remove the root you have in there. This works. Not sure which client api you are using. This is using the latest.
FilesResource.ListRequest request = service.Files.List();
request.MaxResults = 1000;
request.Q = "mimeType='application/vnd.google-apps.folder' and trashed=false and title='myFolder'";

Here is a code snippet uses Google.Apis.Drice.V2 Client Library that can be used for locate a folder in Google Drive.
using Google.Apis.Drive.v2;
using Google.Apis.Drive.v2.Data;
using Google.Apis.Discovery;
using Google.Apis.Upload;
string search = string.Format("title = '{0}' and mimeType =
'application/vnd.google-apps.folder'",folderName);
IList<File> files = new List<File>();
try
{
//List all of the files and directories for the current user.
// Documentation: https://developers.google.com/drive/v2/reference/files/list
FilesResource.ListRequest list = _service.Files.List();
list.MaxResults = 1000;
if (search != null)
{
list.Q = search;
}
FileList filesFeed = list.Execute();
//// Loop through until we arrive at an empty page
while (filesFeed.Items != null)
{
// Adding each item to the list.
foreach (File item in filesFeed.Items)
{
files.Add(item);
}
// We will know we are on the last page when the next page token is
// null.
// If this is the case, break.
if (filesFeed.NextPageToken == null)
{
break;
}
// Prepare the next page of results
list.PageToken = filesFeed.NextPageToken;
// Execute and process the next page request
filesFeed = list.Execute();
}
}
catch (Exception ex)
{
// In the event there is an error with the request.
Console.WriteLine(ex.Message);
}

Related

Copying a file and adding a permission in the same batch request in Google Drive Api v3

I have the following code that I want to chance using batch. In this code, first I create a copy of a file, and then using the id of the new file, I am adding a permission.
File readOnlyFile = new File();
readOnlyFile.Name = newFileName.Replace(' ', '-') + "_assess";
readOnlyFile.Parents = new List<string> { targetFolderId };
FilesResource.CopyRequest fileCreateRequest = _driveService.Files.Copy(readOnlyFile, fileId);
string readOnlyFileId = fileCreateRequest.Execute().Id;
if (readOnlyFileId != null)
{
newPermission.ExpirationTime = expirationDate;
newPermission.Type = "anyone";
newPermission.Role = "reader";
PermissionsResource.CreateRequest req = _driveService.Permissions.Create(newPermission, readOnlyFileId);
req.SendNotificationEmail = false;
req.Execute();
}
However, I am puzzled when trying to use batch for this task since I will need the id of the newly copied file to add permission. Below is my initial attempt where I do not know how to proceed after batch.Queue(fileCreateRequest, callback). I can add new action to the batch to add permission. But, I do not know how to get the id of the file. Any suggestions? I need to do this for three different files.
var batch = new BatchRequest(_driveService);
BatchRequest.OnResponse<Permission> callback = delegate (
Permission permission,
RequestError error,
int index,
System.Net.Http.HttpResponseMessage message)
{
if (error != null)
{
// Handle error
Console.WriteLine(error.Message);
}
else
{
Console.WriteLine("Permission ID: " + permission.Id);
}
};
Permission newPermission = new Permission();
File readOnlyFile = new File();
readOnlyFile.Name = newFileName.Replace(' ', '-') + "_assess";
readOnlyFile.Parents = new List<string> { targetFolderId };
FilesResource.CopyRequest fileCreateRequest = _driveService.Files.Copy(readOnlyFile, fileId);
batch.Queue(fileCreateRequest, callback);
To upload and to configure permissions of a file are two different operations that cannot be batched together. Your approach is correct, you only have to use set up the permissions in a second call.
After uploading the files and retrieving the ids as you do, you have to create a second call to create the permissions.
There is no way to do it in a single request, because for setting up the permissions you need the id of the file; and that is only created after finishing the upload. If you need any more clarification, please ask me without hesitating.

Is there a way to recursive searching folders in Mailkit?

Hope to not get boring with my Mailkit questions but I preffer asking them here in order to help others in the future if they need this help as well.
I need a method for searching a folder. I basically check if it exists and I'm intended to obviously open in if I need to work on it. The thing is that depending on the mailserver this could get a little messy because not every mailserver allows to create folders on the first level and so on (sigh).
Is there any way to recursively search for a folder and get its MailFolder object?
This is my actual code, which is pretty messy, "should" work in just level 2 folder and fails in carpeta.GetSubfolders() because I'm blowing my mind with folders, subfolers and where could I use the .Open method.
I actually have a method to check if the folder exists (the following one) and another to open it, so one problem calls to another :'D
private bool ExisteCarpeta(string nombreCarpetaABuscar)
{
try
{
imap.Inbox.Open(FolderAccess.ReadOnly);
var toplevel = imap.GetFolder(imap.PersonalNamespaces[0]);
var carpetasNivel1 = toplevel.GetSubfolders();
var carpeta = carpetasNivel1.FirstOrDefault(x => x.FullName.Equals(nombreCarpetaABuscar, StringComparison.InvariantCultureIgnoreCase));
carpeta.GetSubfolders();
return carpeta != null;
}
catch (Exception ex)
{
string mensaje = "Ha habido un problema comprando la existencia de la carpeta en el correo. \n";
throw new Exception(mensaje, ex);
}
}
You could do something like this:
static IMailFolder FindFolder (IMailFolder toplevel, string name)
{
var subfolders = toplevel.GetSubfolders ().ToList ();
foreach (var subfolder in subfolders) {
if (subfolder.Name == name)
return subfolder;
}
foreach (var subfolder in subfolders) {
var folder = FindFolder (subfolder, name);
if (folder != null)
return folder;
}
return null;
}
You could use the above method like this:
var toplevel = imap.GetFolder (imap.PersonalNamespaces[0]);
var sent = FindFolder (toplevel, "Sent Items");

Searching file to download in google drive c#

I am trying to create a program that will download image files in my google drive. I was able to do so, however when I am trying to search a file to return a specific file I always got an error when using the 'name' field which is base on this website https://developers.google.com/drive/v3/web/search-parameters. I don't really know the problem. This is my code
GoogleHelper gh = new GoogleHelper();//calling
DriveService service = GoogleHelper.AuthenticateServiceAccount(email, securityPath);
List<String> file = GoogleHelper.GetFiles(service,
"mimeType='image/jpeg' and name contains 'aa'");
String newFile = newPath+id;
gh.DownloadFile(service, file[0],newPath);
//get File Method:
public static List<String> GetFiles(DriveService service, string search)
{
List<String> Files = new List<String>();
try
{
//List all of the files and directories for the current user.
FilesResource.ListRequest list = service.Files.List();
list.MaxResults = 1000;
if (search != null)
{
list.Q = search;
}
FileList filesFeed = list.Execute();
// MessageBox.Show(filesFeed.Items.Count);
//// Loop through until we arrive at an empty page
while (filesFeed.Items != null)
{
// Adding each item to the list.
foreach (File item in filesFeed.Items)
{
Files.Add(item.Id);
}
// We will know we are on the last page when the next page token is
// null.
// If this is the case, break.
if (filesFeed.NextPageToken == null)
{
break;
}
// Prepare the next page of results
list.PageToken = filesFeed.NextPageToken;
// Execute and process the next page request
filesFeed = list.Execute();
}
}
catch (Exception ex)
{
// In the event there is an error with the request.
Console.WriteLine(ex.Message);
MessageBox.Show(ex.Message);
}
return Files;
}
If we check the documentation Search for Files
name string contains1, =, != Name of the file.
They also show it being used
name contains 'hello' and name contains 'goodbye'
Now the file.list method returns a List of file resources. If you check file resources name is not a parameter title is.
So if you do
mimeType='image/jpeg' and (title contains 'a')
Your request will work.
Now the reason the documentation is wrong is that you are using the Google Drive v2 API and the documentation has apparently been updated for Google Drive v3 which you guessed it uses name instead of title for a file.
IMO there should be two because well its just different APIs here.

Tfs Check-in using PendAdd: The array must contain at least one element

So I'm having a problem with automating my code to check-in files to TFS, and it's been driving me up the wall! Here is my code:
string location = AppDomain.CurrentDomain.BaseDirectory;
TfsTeamProjectCollection baseUserTpcConnection = new TfsTeamProjectCollection(uriToTeamProjectCollection);
IIdentityManagementService ims = baseUserTpcConnection.GetService<IIdentityManagementService>();
TeamFoundationIdentity identity = ims.ReadIdentity(IdentitySearchFactor.AccountName, #"PROD1\JR", MembershipQuery.None, ReadIdentityOptions.None);
TfsTeamProjectCollection impersonatedTpcConnection = new TfsTeamProjectCollection(uriToTeamProjectCollection, identity.Descriptor);
VersionControlServer sourceControl = impersonatedTpcConnection.GetService<VersionControlServer>();
Workspace workspace = sourceControl.CreateWorkspace("MyTempWorkspace", sourceControl.AuthorizedUser);
String topDir = null;
try
{
Directory.CreateDirectory(location + "TFS");
String localDir = location + "TFS";
workspace.Map("$/Automation/", localDir);
workspace.Get();
destinationFile = Path.Combine(localDir, Name + ".xml");
string SeconddestinationFile = Path.Combine(localDir, Name + ".ial");
bool check = sourceControl.ServerItemExists(destinationFile, ItemType.Any);
PendingChange[] pendingChanges;
File.Move(sourceFile, destinationFile);
File.Copy(destinationFile, sourceFile, true);
File.Move(SecondsourceFile, SeconddestinationFile);
File.Copy(SeconddestinationFile, SecondsourceFile, true);
if (check == false)
{
workspace.PendAdd(localDir,true);
pendingChanges = workspace.GetPendingChanges();
workspace.CheckIn(pendingChanges, Comments);
}
else
{
workspace.PendEdit(destinationFile);
pendingChanges = workspace.GetPendingChanges();
workspace.CheckIn(pendingChanges, Comments);
}
and the problem is that whenever it's NEW files (PendEdit works correctly when the files already exist in TFS) that my code is attempting to check in, and it runs through this code:
if (check == false)
{
workspace.PendAdd(localDir,true);
pendingChanges = workspace.GetPendingChanges();
workspace.CheckIn(pendingChanges, Comments);
}
The files, instead of being in the included changes in pending changes, are instead in the excluded changes like so:
and when the line that actually does the check-in runs, I'll get a "The array must contain at least one element" error, and the only way to fix it is to manually add those detected changes, and promote them to included changes, and I simply can't for the life of me figure out how to do that programatically though C#. If anyone has any guidance on what direction I should take for this, I would really appreciate it! Thank you!
Edit: I've also discovered another way to solve this by reconciling the folder, which also promotes the detected changes, but again the problem is I can't seem to figure out how to program that to do it automatically.
I know that running the visual studio developer command prompt, redirecting to the folder that this mapping is in, and the running "tf reconcile /promote" is one way, but I can only automate that as far as the /promote part, because that brings up a toolbox that a user would have to input into, which defeats the purpose of the automation. I'm at a loss.
Next Edit in response to TToni:
Next Edit in response to TToni:
I'm not entirely sure if I did this CreateWorkspaceParameters correctly (see picture 1), but this time it gave the same error, but the files were not even in the excluded portions. They just didn't show up anywhere in the pending changes (see picture 2).
Check this blog:
The workspace has a method GetPendingChangesWithCandidates, which actually gets all the “Excluded” changes. Code snippet is as below:
private void PendChangesAndCheckIn(string pathToWorkspace)
{
//Get Version Control Server object
VersionControlServer vs = collection.GetService(typeof
(VersionControlServer)) as VersionControlServer;
Workspace ws = vs.TryGetWorkspace(pathToWorkspace);
//Do Delete and Copy Actions to local path
//Create a item spec from the server Path
PendingChange[] candidateChanges = null;
string serverPath = ws.GetServerItemForLocalItem(pathToWorkspace);
List<ItemSpec> its = new List<ItemSpec>();
its.Add(new ItemSpec(serverPath, RecursionType.Full));
//get all candidate changes and promote them to included changes
ws.GetPendingChangesWithCandidates(its.ToArray(), true,
out candidateChanges);
foreach (var change in candidateChanges)
{
if (change.IsAdd)
{
ws.PendAdd(change.LocalItem);
}
else if (change.IsDelete)
{
ws.PendDelete(change.LocalItem);
}
}
//Check In all pending changes
ws.CheckIn(ws.GetPendingChanges(), "This is a comment");
}

Exchange Web Service, move an item from Inbox it gets removed from Inbox but doesn't show up in the destination Folder

I am working on a client that access an Exchange Web Service via a web reference. (not the Managed API). This is the first time I'm worked with EWS so I hope its just a simple mistake that I overlooked.
I have a method called MoveItem that is supposed to take email message and move it from the Inbox to destinationFolder. When I run this code, the item does disappear from the Inbox however it never shows up in the destination folder. I've spent a couple of days looking at examples online and I've also not been able to find anyone else that has had a similar issue. Can anyone tell me what I am doing wrong? Thanks in advance
Scott
static void MoveItem(ExchangeServiceBinding esb, BaseFolderType destinationFolder, MessageType msg)
{
ItemIdType[] items = new ItemIdType[1] { (ItemIdType)msg.ItemId };
BaseFolderIdType destFolder = destinationFolder.FolderId;
MoveItemType request = new MoveItemType();
request.ItemIds = items;
request.ToFolderId = new TargetFolderIdType();
request.ToFolderId.Item = destFolder;
try
{
MoveItemResponseType response = esb.MoveItem(request);
ArrayOfResponseMessagesType aormt = response.ResponseMessages;
ResponseMessageType[] rmta = aormt.Items;
foreach (ResponseMessageType rmt in rmta)
{
if (rmt.ResponseClass == ResponseClassType.Error)
{
throw new Exception("Item move failed.");
}
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
Definitely not an expert here, but this is the following code I used to grab an item and move it into a folder:
Folder rootfolder = Folder.Bind(service, WellKnownFolderName.MsgFolderRoot);
rootfolder.Load();
foreach (Folder folder in rootfolder.FindFolders(new FolderView(100)))
{
// Finds the emails in a certain folder, in this case the Junk Email
FindItemsResults<Item> findResults = service.FindItems(WellKnownFolderName.JunkEmail, new ItemView(10));
// Enter your destination folder name below this:
if (folder.DisplayName == "Example")
{
// Stores the Folder ID in a variable
var fid = folder.Id;
Console.WriteLine(fid);
foreach (Item item in findResults.Items)
{
// Load the email, move it to the specified folder
item.Load();
item.Move(fid);
}
}
}
One thing about the EWS is that when moving to a folder, the ID of the folder is key. In this example, I first find the folders in the inbox, then access the messages. Therefore, any code regarding the individual message would go after the folders have been found.
I have same problem. The moved message doesn't exists in folder (outlook.com) but can be retrieved via APIs with new assigned id.
Outlook.com can find it in search with an error while loading message body:
Error: Your request can't be completed right now. Please try again later.

Categories