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
andcTag
properties work differently on containers (folders). ThecTag
value is modified when content or metadata of any descendant of the folder is changed. TheeTag
value is only modified when the folder's properties are changed, except for properties that are derived from descendants (likechildCount
orlastModifiedDateTime
).
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.