Onedrive special App Folder - creating a new folder - c#

I'm working with the OneDrive SDK and have successfully managed to get a reference to my special App folder.
_appFolder = await OneDriveClient.Drive.Special.AppRoot.Request().GetAsync();
From here I want to create a sub folder called say "Deep Purple".
Looking at the C# example code I can do this using:
var folderToCreate = new Item { Name = artistName, Folder = new Folder() };
var newFolder = await OneDriveClient
.Drive
.Items[itemId]
.Children
.Request()
.AddAsync(folderToCreate);
But I'm thinking I already have a reference down to Items[itemId] (my _appFolder is of type Item), so I can just use:
var myNewFolder = await _appFolder.Children.Request().AddAsync(folderToCreate);
But no, as you can see by this image I don't have a Request option.
I'm clearly misunderstanding something.

Your issue is that you are using a Model (object representations of response data) and trying to get a Request, which is only returned from the type RequestBuilder. You are close, though! If you want to add a file to the children of your app folder (which is of type Folder), then your request would look like this:
var newFolder = await oneDriveClient
.Drive
.Items[_appFolder.Id]
.Children
.Request()
.AddAsync(folderToCreate);
At its core, the SDK relies on the OneDriveClient object to generate requests because it knows how to do things like authentication and URL generation. The Models are just containers for information returned from the service. You can use the information in those containers in concert with the client to generate any request you need.

Related

MS Graph SDK: How to add URL segment to filter for specific member type?

I'd like to get group members from Graph. No problem, the API is there. I now want to filter for members that are groups themselves and there even is a sample for this on the docs page:
See the /microsoft.graph.group part of the URL? That's what I want, but via Graph SDK.
Switching the sample to C# to see the corresponding code there is no evidence of this microsoft.graph.group URL part anymore:
Am I blind? How to apply this filter via Graph SDK?
Filtering is not supported by SDK code generator. As an alternative you can add segment to request url manually.
var graphClient = new GraphServiceClient( authProvider );
var requestUrl = graphClient.Groups["{group-id}"]
.TransitiveMembers
.AppendSegmentToRequestUrl("microsoft.graph.group?$count=true");
var group = await new GroupTransitiveMembersCollectionWithReferencesRequest(requestUrl, graphClient, null)
.Header("ConsistencyLevel", "eventual")
.GetAsync();
Graph issue

How do I get accounts from Azure AD?

I have a nice Azure Active Directory set up with a dozen users. (All me!) So I have a Tenant ID, client ID and Client Secret.
I am also working on a simple console application that will function as a public client for this directory. This client also holds a list of usernames and passwords as this is just meant as a simple experiment. Not secure, I know. But I first need to understand how it works...
I do this:
IConfidentialClientApplication client = ConfidentialClientApplicationBuilder
.CreateWithApplicationOptions(options).Build();
And this creates my client app. Works fine.
I also get a token using "https://graph.microsoft.com/.default" and can use this to get all users as JSON:
string result = await GetHttpContentWithToken("https://graph.microsoft.com/v1.0/users",
token.AccessToken);
Although I might want it to be more user-friendly, JSON is fine for now.
How can I check if user is an authorized user?
And no, I don't want complex solutions that require various nuget packages. Just a plain and simple step-by-step explanation. I could probably Google this but I ended up with thousands of results and none were helpful... This should be easy, right?
[EDIT] I first wanted to get a list of users nut that failed because of a typo... (There's a dot before 'default'...)
It took some fooling around but it's not too difficult after all. There are a lot of libraries around Azure but it is all basically just a bunch of HTTP requests and responses. Even in a console application...
I started with making a PublicClientApplicationBuilder first:
var options = new PublicClientApplicationOptions()
{
ClientId = <**clientid**>,
TenantId = <**tenantid**>,
AzureCloudInstance = AzureCloudInstance.AzurePublic,
};
var client = PublicClientApplicationBuilder.CreateWithApplicationOptions(options).Build();
I can also create a ConfidentialClientApplication instead, but this allows me to log in interactively, if need be.
Next, set up the scopes:
var scopes = new List<string>() { "https://graph.microsoft.com/.default" };
As I wanted to log in using username and password, I have to use this:
var token = await client.AcquireTokenInteractive(scopes).ExecuteAsync();
But if I want to log in using code, I can also use this:
var password = new SecureString();
foreach (var c in <**password**>) { password.AppendChar(c); }
var token = await client.AcquireTokenByUsernamePassword(scopes, <**account**>, password).ExecuteAsync();
At this point, I'm authorized as the specified user. So, now all I need is to get whatever data I like, in JSON strings...
public static async Task<string> ExecCmd(string name, string url, string token)
{
HttpClient httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", token);
string result = await GetHttpContentWithToken(url, token);
JObject json = JsonConvert.DeserializeObject(result) as JObject;
File.WriteAllText(name, json.ToString());
return result;
}
As I just want to read the data as text files, I just execute the action in using a specific and write it as formatted JSON to the file . So, using this simple method I can now use this:
await ExecCmd("Profile.txt", "https://graph.microsoft.com/v1.0/me/", token.AccessToken);
await ExecCmd("Groups.txt", "https://graph.microsoft.com/v1.0/groups", token.AccessToken);
await ExecCmd("Users.txt", "https://graph.microsoft.com/v1.0/users", token.AccessToken);
These will provide me with (1) the profile of the current user, (2) the AD groups and (3) the AD users. And probably a bit more...
I can use this ExecCmd to retrieve a lot more data, if I want to. But there's something else to keep in mind! For it all to work, you also need to configure the Azure application and make sure all access rights are assigned and approved!
So, in Azure AD you have to add an "App registration" and fiddle around with the settings... (The Azure experts are horribly shocked now, but when you want to learn, you'd just have to try and fail until you succeed...)
Also set "Default client type" to "public client" for the registered app.
In Azure, with the registered app, you also need to set the proper API permissions! Otherwise, you won't have access. And as I want access to Active Directory, I need to add permissions to "Azure Active Directory Graph". I can do this inside Azure or by using the scope when I call AcquireTokenInteractive(). For example, by using "https://graph.windows.net/Directory.Read.All" instead of "https://graph.windows.net/.default".
Once you've accessed a token interactively, you can also get more tokens using client.AcquireTokenSilent(). It gets a bit tricky from here, especially if you want to access a lot of different items. Fortunately, Active Directory is mostly the directory itself, groups, users and members.
Personally, I prefer to grant access from the Azure website but this is quite interesting.
Anyways, I wanted to authenticate users with Azure and now I know how to do this. It still leaves a lot more questions but this all basically answers my question...
I'll use this as answer, as others might find it useful...

UWP OneDrive storage space

I have a c# UWP App, that makes use of the OneDrive API to store files in the approot (special folder for my App only). I know, that I can get the total space of OneDrive this way, but it doesn't tell me, how much space my App takes.
Is there a fast way to tell, how much space my App takes to store these files there (instead of iterating through all items)?
As Brad said, approot like any other OneDrive item has a metadata. And in item's metadata has a size property which represents size of the item in bytes. So we can use this property to get the total space your app takes.
As App Folder described, we can use GET /drive/special/approot to get your app folder's metadata and when using OneDrive .NET SDK, the code will like:
var item = await oneDriveClient.Drive.Special.AppRoot.Request().GetAsync();
System.Diagnostics.Debug.WriteLine($"{item.Name}'s size is {item.Size}");
However as I tested, when we use this code in UWP, we will encounter a cache issue. Even your app folder's size has changed, this API will return the same value as the first time you run it.
This is because while Get metadata for a OneDrive item, it has an optional request headers if-none-match and if this request header is included and the eTag (or cTag) provided matches the current tag on the file, an HTTP 304 Not Modified response is returned.
And in UWP, using HttpClient will automatically add this header in request, if the eTag is not changed, HttpClient will not get the newest info, it will return the data it cached. According to Item resource type:
Note: The eTag and cTag properties work differently on containers (folders). The cTag value is modified when content or metadata of any descendant of the folder is changed. The eTag value is only modified when the folder's properties are changed, except for properties that are derived from descendants (like childCount or lastModifiedDateTime).
So in most case, app folder's eTag won't change and when we use OneDrive .NET SDK or default HttpClient in UWP to get app folder's metadata, we will get the cached data. To see this clearly, we can use fiddler to trace the network, and we will find in the request headers, If-None-Match is added and the real response from OneDrive is HTTP 304 Not Modified.
To solve this issue, we can use Windows.Web.Http.HttpClient class with HttpBaseProtocolFilter class and HttpCacheControl class to disable the cache like following:
var oneDriveClient = await OneDriveClientExtensions.GetAuthenticatedUniversalClient(new[] { "wl.signin", "onedrive.readwrite" });
var filter = new Windows.Web.Http.Filters.HttpBaseProtocolFilter();
filter.CacheControl.ReadBehavior = Windows.Web.Http.Filters.HttpCacheReadBehavior.MostRecent;
filter.CacheControl.WriteBehavior = Windows.Web.Http.Filters.HttpCacheWriteBehavior.NoCache;
var httpClient = new HttpClient(filter);
var request = new HttpRequestMessage(HttpMethod.Get, new Uri("https://api.onedrive.com/v1.0/drive/special/approot"));
request.Headers.Authorization = new Windows.Web.Http.Headers.HttpCredentialsHeaderValue("Bearer", oneDriveClient.AuthenticationProvider.CurrentAccountSession.AccessToken);
var response = await httpClient.SendRequestAsync(request);
var item = oneDriveClient.HttpProvider.Serializer.DeserializeObject<Item>(await response.Content.ReadAsStringAsync());
System.Diagnostics.Debug.WriteLine($"{item.Name}'s size is {item.Size}");
PS: To make this method work, we need make sure there is no local HTTP cache. So we'd better uninstall the app first and do not use await oneDriveClient.Drive.Special.AppRoot.Request().GetAsync() in the app.
When you fetch your app's folder (via approot) the value of the size property returned on the item should be a reflection of the amount of space your application is using (since for a folder the value is the sum of the size of all files stored within it, at any level).

how to use box api in asp.net web application

I am trying to use box api in an asp.net web application.
Based on the search there are two options to access box account;
By downloading the Box.V2 package using below link containing the required dlls and use that in our application
By using Box SDK containing code and reference that inside our application. Using this approach we can debug the Box.V2 code by adding the project to our solution.
Correct me if I am wrong.
So, I am trying to implement the second approach. Can someone help me move forward by specifying the steps to be taken, minimum .net framework requirement, etc.
Good question, GitHub samples does not mention about the Web (Asp.Net).
It's possible and it looks pretty easy to do once you figure out the the way,
I have seen some answers for Windows apps trying to manually build the authorization URLs etc, but there is an easier way to do it.
Here's how to do it with OAuth,
Install nuget
PM> Install-Package Box.V2
Get the Authcode (this is what's been missing in most examples)
public async Task<ActionResult> Connect()
{
var clientId = "xxxxx";
var clientSecret = "xxxxxx";
var redirectUri = new Uri("http://localhost:xxxx/Home/AuthCallBackAsync");//Your call back URL
var config = new BoxConfig(clientId, clientSecret, redirectUri);
return Redirect(config.AuthCodeUri.ToString());
}
Interesting thing is that the "config" object generates the AuthCodeUri.
This will redirect the user to Consent screen and ask the user to sign in. Once the user "Grants Access" you will get the "Authcode" for your call back URL which can be used to generate accesstoken.
Handle the Auth Callback response
public async Task<ActionResult> AuthCallbackAsync()
{
NameValueCollection parms = Request.QueryString;
var authCode = parms["code"]
//Get "config" - you can store this in session or in a cache.
var config = new BoxConfig(clientId, clientSecret, redirectUri);
var client = new BoxClient(config);
await client.Auth.AuthenticateAsync(authCode);
//Now you will get the accesstoken and refresh token
var accessToken = client.Auth.Session.AccessToken;
var refreshToken = client.Auth.Session.RefreshToken;
//Ready to consume the API
var user = await client.UsersManager.GetCurrentUserInformationAsync();
-------More Api Calls---
}

Getting the File type in Azure Storage

Is it possible to get the file type of an image file or blob in Azure Storage? i have researched everything but no to avail. any response will be appreciated! I was wondering, is there anything that i could add in order to get it? here is my code:
ImageSource wew=new BitmapImage(new Uri("http://sweetapp.blob.core.windows.net/cakepictures/"+newfilename+filetypeofthepicture, UriKind.RelativeOrAbsolute)); //need to get the file type of the image
CakeData.Add(new CakeData { Cakename = item.Cakename, ImagePath = wew });
Each blob has a property called Content-Type which can be set when the blob is uploaded. You can make use of Storage Client Library to fetch blob properties to get its content type property. If you are using .Net Storage Client Library, you could use code below:
var blob = new CloudBlockBlob(new Uri("blob uri"), new StorageCredentials("sweetapp", "account key"));
blob.FetchAttributes();
var contentType = blob.Properties.ContentType;
This would however require you to include the credentials in your client app. If you don't want to do that, other alternative would be to use Shared Access Signature Token and use that to create an instance of StorageCredentials object. You could create this SAS token somewhere on the server.
var credentials = new StorageCredentials(sasToken);
var blob = new CloudBlockBlob(new Uri("blob uri"), credentials);
blob.FetchAttributes();
var contentType = blob.Properties.ContentType;
3rd alternative would be access the registry and get the mime-type based on file extension but I'm not sure if a Windows 8 app would have access to the registry.
Last alternative would be to hard code stuff in your application. There's a predefined set of mime-types which you can hard code in your application and based on the file's extension, you can retrieve the content type.

Categories

Resources