Dropbox C# API v2 List Team folder contents - c#

Good afternoon,
I am trying to get the list of directories from the dropbox API for the team members in business dropbox.
The documentation seems to be somewhat unclear and frustratingly difficult to get contents. Therefore my code could off somewhat and hence why i am having issues. I have a development token for both Team and my admin user.
using (var client = new DropboxTeamClient("my token"))
{
var teamInfo = await client.Team.GetInfoAsync();
var teamName = teamInfo.Name;
var numberOfUsers = teamInfo.NumProvisionedUsers;
var memListResult = await client.Team.MembersListAsync();
foreach (var m in memListResult.Members)
{
var accountId = m.Profile.AccountId;
var email = m.Profile.Email;
Console.WriteLine($"Id {accountId} - email is {email}");
}
var accId = memListResult.Members.First(x => x.Profile.Email.Equals("myEmail"))
?.Profile.AccountId;
var memId = memListResult.Members.First(x => x.Profile.Email.Equals("myEmail"))
?.Profile.TeamMemberId;
var dbx = client.AsAdmin(memId);
try
{
var full = await dbx.Users.GetCurrentAccountAsync();
Console.WriteLine("{0} - {1}", full.Name.DisplayName, full.Email);
await ListRootFolder(dbx, true);
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
private async Task ListRootFolder(DropboxClient dbx)
{
var list = await dbx.Files.ListFolderAsync(string.Empty);
//var tlist = await dbx.
// show folders then files
foreach (var item in list.Entries.Where(i => i.IsFolder))
{
Console.WriteLine("D {0}/", item.Name);
}
foreach (var item in list.Entries.Where(i => i.IsFile))
{
Console.WriteLine("F{0,8} {1}", item.AsFile.Size, item.Name);
}
}
No my issue is that i can only ever get what shows in my directory. So for example i have logged into the web browser into dropbox i have three directories.
|
|- User Dir 'This is my home directory'
|- Team Dir 'This is a directory for the team'
|- Sample folder
The team has access to the Team dir and sample folder. All i would like to do is simply get the list of directories.
I must be doing something completely wrong, i have also tried the overrides for dbx.Files.ListFolderAsync i have set includeMountedFolders parameter to true and still only lists two files in my profile.
I have also tried using the user token instead of the Team token and setting asAdmin.
Apologies on the code is somewhat untidy i just want to get it working before i refactor.
Any help would be appreciated.
Thanks

It sounds like you want to access your "team space". You need to explicitly specify this when calling the API. I recommend reading the Namespace Guide, which covers this in detail.
The .NET SDK supports setting the Dropbox-Api-Path-Root header, via DropboxClient.WithPathRoot.
First, you can get the root info from GetCurrentAccountAsync:
var accountInfo = await dbx.Users.GetCurrentAccountAsync();
Console.WriteLine(accountInfo.RootInfo.RootNamespaceId);
Then, you can access the team shared space by using DropboxClient.WithPathRoot to set the Dropbox-Api-Path-Root header as desired, like:
dbx = dbx.WithPathRoot(new PathRoot.NamespaceId(accountInfo.RootInfo.RootNamespaceId));
var res = await this.client.Files.ListFolderAsync(path: "");
foreach (var entry in res.Entries)
{
Console.WriteLine(entry.Name);
}

Related

AWS Cost Explorer API doesn't return Resource ID

I'm testing the AWS Cost Explorer API (I'm using the .NET SDK), in particular the GetCostAndUsageWithResources method to get the costs split by resource.
This is the code I'm testing with:
string nextPageToken = null;
do
{
var costRequest = new GetCostAndUsageWithResourcesRequest()
{
Granularity = Granularity.HOURLY,
GroupBy = {
new GroupDefinition() {
Key = "RESOURCE_ID",
Type = GroupDefinitionType.DIMENSION
}
},
Metrics = { "BlendedCost" },
NextPageToken = nextPageToken
};
var costResponse = await client.GetCostAndUsageWithResourcesAsync(costRequest);
nextPageToken = costResponse.NextPageToken;
foreach (var resultByTime in costResponse.ResultsByTime)
{
foreach (var instanceGroup in resultByTime.Groups)
{
var instanceId = instanceGroup.Keys.First();
if(g.Keys.First() != "NoResourceId" && !g.Keys.First().StartsWith("i-"))
{
Debugger.Break(); //NEVER gets hit
}
}
}
} while (!string.IsNullOrEmpty(nextPageToken));
However, as you can see from the comment in the code, I have an issue: the resource ID (which is the dimension I'm grouping by) seems to only be retrieved correctly for EC2 machine instances (IDs that start with i-). Otherwise, all other results have the ID key set to NoResourceId
What am I doing wrong here? Why does the Cost Explorer API only populate the Resource ID of EC2 instances, and all others are not identified? What if I want to know the costs of all other AWS services, how do I identify to which service the result belongs?
Am I doing something wrong here in the way I invoke the API? What am I missing?

Downloading attachments with in sub folders using graph api and C#

I'm creating a solution to download attachments from an outlook365 account. The inbox of this account has subfolders and folders within the subfolders. The structure looks like below.
I've been trying to download the attachments but I'm only able to get the attachment from the messages in the main inbox.
But I want to look into the subfolders. So by studying the Microsoft graph document (https://learn.microsoft.com/en-us/graph/api/attachment-get?view=graph-rest-1.0&tabs=http#http-request) I found the below HTTP URL request.
GET /me/mailFolders/{id}/childFolders/{id}/.../messages/{id}/attachments/{id}
GET /users/{id | userPrincipalName}/mailFolders/{id}/childFolders/{id}/messages/{id}/attachments/{id}
GET /me/mailFolders/{id}/childFolders/{id}/.../messages/{id}/attachments/{id}/$value
GET /users/{id | userPrincipalName}/mailFolders/{id}/childFolders/{id}/messages/{id}/attachments/{id}/$value
I'm pretty new to C# I'm having a hard time converting above mentioned URL method to C#. Below is the current code I use to grab the messages and expand the attachments.
public static async Task<IMailFolderMessagesCollectionPage> GetAttachmentToday()
{
var DateToDay = DateTime.Now.ToString("dd.MM.yyyy");
var SearchOption = new List<QueryOption>
{
new QueryOption("search", $"%22received:{DateToDay}%22")
};
try
{
var attachments = await graphClient.Me.MailFolders.Inbox.Messages
.Request(SearchOption)
.Top(5)
.Select(a => new
{
a.Subject,
a.HasAttachments
})
.Expand("attachments")
.GetAsync();
return attachments;
}
catch(ServiceException ex)
{
Console.WriteLine($"Error getting events: {ex.Message}");
return null;
}
}
I can't figure out how to implement the Microsoft document URL suggestion to work with var attachments = await graphClient.Me.MailFolders.Inbox.Messages. Hope someone can point me down the right path.
I figure this out and used the example HTML code given by Microsoft documents. Which is below.
GET /me/mailFolders/{id}/childFolders/{id}/.../messages/{id}/attachments/{id}
GET /users/{id | userPrincipalName}/mailFolders/{id}/childFolders/{id}/messages/{id}/attachments/{id}
GET /me/mailFolders/{id}/childFolders/{id}/.../messages/{id}/attachments/{id}/$value
GET /users/{id | userPrincipalName}/mailFolders/{id}/childFolders/{id}/messages/{id}/attachments/{id}/$value
So based on the above code I came up with the below C# code.
//To get the first supfolder and it's ID.
var FirstSubFolderIDs = await graphClient.Me.MailFolders["Inbox"].ChildFolders
.Request()
.Select(fid => new
{
fid.Id,
fid.DisplayName
})
.GetAsync();
foreach(var FirstSubFolderID in FirstSubFolderIDs)
{
if(FirstSubFolderID.Id != null)
{ //Using the above ID to get the second folder and it's ID.
var SecondSubFolderIDs = await graphClient.Me.MailFolders["Inbox"]
.ChildFolders[$"{FirstSubFolderID.Id}"]
.ChildFolders
.Request()
.Select(sid => new
{
sid.Id,
sid.DisplayName
})
.GetAsync();
foreach (var SecondSubFolderID in SecondSubFolderIDs)
{
if(SecondSubFolderID.Id != null)
{ //Continuing on using the first 2 ID's to get the 3rd folder and it's ID.
var ThirdSubFolderIDs = await graphClient.Me.MailFolders["Inbox"]
.ChildFolders[$"{FirstSubFolderID.Id}"]
.ChildFolders[$"{SecondSubFolderID.Id}"]
.ChildFolders
.Request()
.Select(tid => new
{
tid.Id,
tid.DisplayName,
})
.GetAsync();
foreach (var ThirdSubFolderID in ThirdSubFolderIDs)
{
if(ThirdSubFolderID.DisplayName == "New")
{ //Now you're at the last folder where the emails are at.
var GetMessageAttachments = await graphClient.Me.MailFolders["Inbox"]
.ChildFolders[$"{FirstSubFolderID.Id}"]
.ChildFolders[$"{SecondSubFolderID.Id}"]
.ChildFolders[$"{ThirdSubFolderID.Id}"]
.Messages
//.Request(SearchOption)
.Request()
.Expand("attachments")
.Select(gma => new
{
gma.Id,
gma.Subject,
gma.HasAttachments,
gma.Attachments
})
.GetAsync();
//Get Message count that includes attachments
var MessageCount = GetMessageAttachments.Count;
if (MessageCount != 0)
{
//Do what you want here
}
Decided to answer my question so someone else might find this helpful.

Get the current iteration path from TFS

I'm trying to get the current iteration path for the teams TFS project. The way I'm trying to do this is by using the blog from http://blog.johnsworkshop.net/tfs11-api-reading-the-team-configuration-iterations-and-areas/ . I start by getting the team configurations from the following code:
TfsTeamProjectCollection tpc = TFSConncetion(#"http://tfs/url");
var configSvc = tpc.GetService<TeamSettingsConfigurationService>();
var configs = configSvc.GetTeamConfigurationsForUser(projectUri);
The problem with this is that my configs is always null, even though I'm a member of the team. I'm positive my projects URI is correct as well. After this I would get the team settings and use that to display the current iteration path.
TeamSettings ts = config.TeamSettings;
Console.WriteLine(ts.CurrentIterationPath);
Even if this didn't work I can still query the iteration dates from the team setting to get the one iteration that has a start date before today and finish date after today. The main problem is that I can't get my TeamSettingsConfigurationService to return anything but null when I try to get the team configurations with my projects URI.
There must be something wrong with your server connection or the project uri you're passing as the other code looks okay.
Maybe try something like this:
TfsTeamProjectCollection tpc = new TfsTeamProjectCollection(new Uri("http://server:8080/tfs/collection"),
new System.Net.NetworkCredential(tfsUserName, tfsPassword));
tpc.EnsureAuthenticated();
Connect to Team Foundation Server from a Console Application
There is a good sample here which you can download (WPF client) and it will allow you to select a server connection, Team Project and Team:
TFS API Part 46 (VS11) – Team Settings
You can step through it and check the values you're passing into your code.
The sample gets the team configuration information is the same way you have in your code.
TeamSettingsConfigurationService teamConfig = tfs.GetService<TeamSettingsConfigurationService>();
var configs = teamConfig.GetTeamConfigurationsForUser(new[] { projectInfo.Uri });
Once you have the collection of TeamConfiguration items then you need TeamSettings.CurrentIterationPath
I actually got the answer myself without using TeamSettingsConfigurationService at all. Here's how I did it:
private static XmlNode currentIterationNode;
TfsTeamProjectCollection tpc = TFSConncetion(#"http://tfs/url");
ICommonStructureService4 css = tpc.GetService<ICommonStructureService4>();;
WorkItemStore workItemStore = new WorkItemStore(tpc);
foreach (Project teamProject in workItemStore.Projects)
{
if (teamProject.Name.Equals("TeamProjectNameGoesHere"))
{
NodeInfo[] structures = css.ListStructures(teamProject.Uri.ToString());
NodeInfo iterations = structures.FirstOrDefault(n => n.StructureType.Equals("ProjectLifecycle"));
if (iterations != null)
{
XmlElement iterationsTree = css.GetNodesXml(new[] { iterations.Uri }, true);
XmlNodeList nodeList = iterationsTree.ChildNodes;
currentIterationNode = FindCurrentIteration(nodeList);
String currentIterationPath = currentIterationNode.Attributes["Path"].Value;
}
}
}
Where currentIterationPath is the current iteration path from TFS. The key to doing this was to get the NodeInfo[] array of structures and the NodeInfo iterations from these two lines of code I got from chamindacNavantis https://social.msdn.microsoft.com/Forums/vstudio/en-US/4b785ae7-66c0-47ee-a6d2-c0ad8a3bd420/tfs-get-iteration-dates-metadata?forum=tfsgeneral:
NodeInfo[] structures = css.ListStructures(teamProject.Uri.ToString());
NodeInfo iterations = structures.FirstOrDefault(n => n.StructureType.Equals("ProjectLifecycle"));
After that I created an xml with nodes of every iteration inside the team project. These nodes also have the start date and end dates of each iteration. So I checked each node for a start date before DateTime.Now and finish date after DateTime.Now, which is all FindCurrentIteration(nodeList) does.
And that will give you the current iteration node.
The simplest way I've found to do it was by using ICommonStructureService4 and TeamSettingsConfigurationService methods:
static TfsTeamProjectCollection _tfs = TfsTeamProjectCollectionFactory
.GetTeamProjectCollection("<tfsUri>")
(...)
static string GetCurrentIterationPath()
{
var css = _tfs.GetService<ICommonStructureService4>();
var teamProjectName = "<teamProjectName>";
var project = css.GetProjectFromName(teamProjectName);
var teamName = "<teamName>";
var teamSettingsStore = _tfs.GetService<TeamSettingsConfigurationService>();
var settings = teamSettingsStore
.GetTeamConfigurationsForUser(new[] { project.Uri })
.Where(c => c.TeamName == teamName)
.FirstOrDefault();
if (settings == null)
{
var currentUser = System.Threading.Thread.CurrentPrincipal.Identity.Name;
throw new InvalidOperationException(
$"User '{currentUser}' doesn't have access to '{teamName}' team project.");
}
return settings.TeamSettings.CurrentIterationPath;
}

SPMeta2 System.InvalidCastException while trying to deploy model

I am currently trying to create a simple list in Sharepoint 365, using SPMeta2 framework. I have tried doing it according to the documentation, and got an exception, then I've decided to simply copy code from their samples, located here Now, when I'm trying to deploy my model I keep getting System.InvalidCastException. It says it needs SiteModelHost, but when I give it SiteModelHost I get same exception, saying WebModelHost. Obviously, when I give it web it asks for site. I would be grateful for any pointers.
Here is my code for deploying the model:
class Program
{
static void Main (string[] args)
{
var targetSite = new Uri("https://url.com/");
var login = "***.com";
var password = "1234";
var securePassword = new SecureString();
foreach (char c in password)
{
securePassword.AppendChar(c);
}
var onlineCredentials = new SharePointOnlineCredentials(login, securePassword);
var model = SPMeta2Model
.NewSiteModel(site =>
{
site
.WithFields(fields =>
{
fields
.AddField(FieldModels.Contact)
.AddField(FieldModels.Details);
})
.WithContentTypes(contentTypes =>
{
contentTypes
.AddContentType(ContentTypeModels.CustomItem)
.AddContentType(ContentTypeModels.CustomDocument);
})
.WithLists(lists =>
{
lists
.AddList(ListModels.TestLibrary)
.AddList(ListModels.TestList)
.AddList(ListModels.TestLinksList);
});
});
using (var context = new ClientContext(targetSite))
{
context.Credentials = onlineCredentials;
var povisionService = new CSOMProvisionService();
povisionService.DeployModel(WebModelHost.FromClientContext(context), model); // WebModelHost/SiteModelHost - same exception
}
Easy.
SPMeta2 allows to several types of models.
Site model reflects and contains all artefacts which could be deployed at site level - site features, custom actions, site fields, content types and so on.
Site model should be deployed within 'site model host'.
Web model reflects and contains all artefacts which could be deployed at web level - web features, lists, list views and so on.
Web model should be deployed within 'web model host'.
With CSOM provision, SiteModelHost.FromClientContext(context) and WebModelHost.FromClientContext(context) should be used to push site or web model accordingly.
Here is a working code for site model.
We removed lists (they belong to web) and use SiteModelHost.
var siteModel = SPMeta2Model
.NewSiteModel(site =>
{
site
.WithFields(fields =>
{
fields
.AddField(FieldModels.Contact)
.AddField(FieldModels.Details);
})
.WithContentTypes(contentTypes =>
{
contentTypes
.AddContentType(ContentTypeModels.CustomItem)
.AddContentType(ContentTypeModels.CustomDocument);
});
});
using (var context = new ClientContext(targetSite))
{
var povisionService = new CSOMProvisionService();
povisionService.DeployModel(SiteModelHost.FromClientContext(context), siteModel);
}
And the web model here.
We removed fields/content types, and use only lists plus WebModelHost.
var webModel = SPMeta2Model
.NewWebModel(web =>
{
web
.WithLists(lists =>
{
lists
.AddList(ListModels.TestLibrary)
.AddList(ListModels.TestList)
.AddList(ListModels.TestLinksList);
});
});
using (var context = new ClientContext(targetSite))
{
var povisionService = new CSOMProvisionService();
povisionService.DeployModel(WebModelHost.FromClientContext(context), webModel);
}
Finally, here are several links to get started:
Sample project at github
https://github.com/SubPointSolutions/spmeta2.contoso
SPMeta2 Yammer Group
http://yammer.com/spmeta2feedback
Some documentation (work in progress)
http://docs.subpointsolutions.com/spmeta2
Let me know how it goes, and if you need further assistance.
Cheers!

How to get all the documents in a folder in Google Docs

I can get all the documents in Google Docs using
public DocumentsFeed GetDocs()
{
DocumentsListQuery query = new DocumentsListQuery();
DocumentsFeed feed = service.Query(query);
return feed;
}
But how can I get the documents in a particular folder? I wan to discover the list of folders and then populate the folders in a tree view. On selection of a folder, I shall like to get the documents in that folder.
To get the folder, I am using
public DocumentsFeed GetFolders()
{
FolderQuery query = new FolderQuery("root"); //http://docs.google.com/feeds/documents/private/full
DocumentsFeed feed = service.Query(query);
return feed;
}
For the service, I am using private DocumentsService service;
Can somebody help?
Another guy using the API has described how he does it:
var docService = new DocumentsService("company-app-version");
docService.setUserCredentials("username", "password");
using Google.GData.Client;
using Google.GData.Extensions;
using Google.GData.Documents;
// snipped method declaration etc
var docService = new DocumentsService("company-app-version");
docService.setUserCredentials("username", "password");
var folderList = docService.Query(new FolderQuery());
var fLinks = folderList.Entries.Select(e =>
new
{
// note how to get the document Id of the folder
Id = DocumentsListQuery.DocumentId(e.Id.AbsoluteUri),
Name = e.Title.Text
});
foreach (var folder in fLinks)
{
Console.WriteLine("Folder {0}", folder.Name);
var fileList = docService.Query(
new SpreadsheetQuery()
{
// setting the base address to the folder's URI restricts your results
BaseAddress = DocumentsListQuery.folderBaseUri + folder.Id
});
foreach (var file in fileList.Entries)
{
Console.WriteLine(" - {0}", file.Title.Text);
}
}
Source:
http://jtnlex.com/blog/2010/06/09/google-docs-api-get-all-spreadsheetsdocs-in-a-folder/
Here's how :
instead of typing the name of the folder , use the resourceID of the folder query = new FolderQuery(FolderEntry.ResourceId);
But first you need to get ALL documents in the root and enable showing folders : query.ShowFolders = true; , that's how you get the resourceId's of the docs in the root and
folders!
Hope this helps !

Categories