Why does MS Graph Thumbnail URL change after document changes - c#

I am using MS Graph c# SDK to pull the thumbnail links for some docx and pdf files. The issue I was planning to store these links in my db to call them quickly for the front end. However, I noticed anytime a document is saved the link changes. However, the old URL still works and it also includes the latest changes. Is it safe to store the URLs and reuse them or does it not matter as my current experiment is showing:
GraphServiceClient graphClient = new GraphServiceClient( authProvider );
var thumbnails = await graphClient.Me.Drive.Items["{driveItem-id}"].Thumbnails
.Request()
.GetAsync();

The URLs change to ensure that browser will invalidate their cache and render an updated thumbnail. We generally don't recommend caching the URLs yourself because there may be scenarios that trigger an expiration of the URL, at which point what you have cached will fail to work. However, as long as you handle failures of cache URLs by falling back to getting a new thumbnail URL maybe it'll be ok for your scenario.

Related

Using MS Graph to Read Excel Contents Through Sharepoint

I'm attempting to use MS Graph to parse the contents of excel files and sync the data with other business-line applications. The issue I'm running into is actually getting at the data in excel.
I'm using a ClientCredentialProvider authenticating to an Azure AD App Registration which has FullControl and Read.All permissions in my tenant to create my GraphServiceClient, and can successfully query the Site via ID, and even see the document library I'm trying to access, but the Items comes up empty. See below
var result = _graphService.Client
.Sites["my-site-id"] // This works
.Drives["site-drive-id"] // This works to find the document library
//.Lists["list-id-corresponding-to-folder"] // This also works to find that folder
.Items // ****This is null****
.Request()
.GetAsync()
.Result;
I tried using the Lists property (as noted above) because as I understand it document libraries in SharePoint are really just lists, but again the Items enumeration yields no results.
I can't find documentation on Microsoft's site on this use case, and I notice using the MS Graph Explorer that the returned object doesn't have an "items" field (or many properties in the Microsoft.Graph.Site class), but I would think there is some way to get this field populated since it's implemented in the Microsoft.Graph namespace. Not sure if I'm missing some permissions step or what, but if I can access the site with FullControl I should be able to access all its contents...
I can't use Client.Me (personal drive) as a source location because 1) the application doesn't run under my permissions and 2) there is a need to read multiple files; the idea would be just provide the needed site/drive/item ID's and get the documents.
Is there some other way I should be going about this?
#broccoli_rob,
MS Graph has not exposed the functionality of enumerating all items in a drive. Instead, you can only list children or get item by id.
We suggest you use /drive/root:/{item-path} to get items in a folder. And you can vaild the endpoint in Graph explorer:
BR

Microsoft Graph .NET Client Library: Upload file to document center

I want to create a file in a Sharepoint document center using Microsoft Graph .NET Client Library. It seems that I can successfully create the file but it is not visible to anyone except the app which created it. When the app creates a file in an "ordinary" document library with exactly the same code then the file is visible to other users (as expected).
Here is the code I use:
var result = await client.Drives[documentCenterDriveId]
.Items[subfolderId]
.ItemWithPath(fileName)
.Content
.Request()
.PutAsync<DriveItem>(new MemoryStream(buffer));
Afterwards I can query the folder and see that the file is there:
var result = await client.Drives[documentCenterDriveId]
.Items[subfolderId]
.Children
.Request()
.GetAsync();
However when go to the Microsoft Graph Explorer, sign in with my personal credentials (i.e. not the same as the app) and issue the following GET request
https://graph.microsoft.com/v1.0/drives/documentCenterDriveId/items/subfolderId/children
I get an empty list. If I do the same for the "ordinary" document library it works as expected.
I checked the permissions of the file in the document center with
var perms = await client.Drives[documentCenterDriveId]
.Items[fileId]
.Permissions
.Request()
.GetAsync();
and the read role is granted to a group my account belongs to. This means I should be able to see it.
How can I diagnose the source of this issue? Are there logs somewhere in Sharepoint where I could find out more? There are no error messages or exceptions when I run my code.
I found out that I also have to checkin the file.
await client.Drives[documentCenterDriveId].Items[result.Id].Checkin().Request().PostAsync();
I don't know why I do not need to checkin the file after upload in a "ordinary" document library but in the document center I have to.

Keep getting old version, even after changing the Default Service Version on azure blob (inorder to set the content disposition header)

background:
I'm trying to force the browser to download an image in response to a button (or link) click, instead of showing it inline. I need this to work cross browsers, so HTML5 attributes aren't enough.
The Image is stored in a blob (azure storage services).
What I tried:
To set the DefaultServiceVersion to 2013-08-15 so the contentDisposition will work. (example from here Azure Storage API ContentDisposition):
var cloudStorageAccount = new CloudStorageAccount(new StorageCredentials("accountname", "accountkey"), false);
var serviceProperties = cloudStorageAccount.CreateCloudBlobClient().GetServiceProperties();
serviceProperties.DefaultServiceVersion = "2013-08-15";
cloudStorageAccount.CreateCloudBlobClient().SetServiceProperties(serviceProperties);
To set the content disposition property (example from http://www.tuicool.com/articles/AFbmY3):
blob.Properties.ContentDisposition = "attachment; filename=" + downloadName;
To Call the image from a link click\window.open(image_url)\window.location = image_url.
With fiddler in the background.
The problem:
The image is shown by IE as an in-line image. Checking on fiddler and see that:
The contentDisposition doesn't exist in the response header.
The x-ms-version in the response is not the one I set as the default one. I'm Keep getting the old version 2009-09-19.
So I also tried to generate the request directly from fiddler, with the x-ms-version specified in the request header. This does work and I'm getting the response I'm expecting for, with the contentDisposition property and the right x-ms-version (the one I added to the request - 2013-08-15).
I understand that the problem is with the default service version and when i check (while debugging) the value of the DefaultServiceVersion property I do see the right value(2013-08-15), but still the response contains the old value.
I can't add x-ms-version to the header while generating the request from a link (or from window.open) and I don't really understand why the default value I added isn't working.
Thanks in advance for any help or suggestion how to solve this issue.
I think I know what's happening. Please check out this link: http://msdn.microsoft.com/en-us/library/azure/dd894041.aspx (Go to the section titled: Requests Via Anonymous Access which reads)
If a request to the Blob service does not specify the x-ms-version
header, and the default version for the service has not been set using
Set Blob Service Properties, then the earliest version of the Blob
service is used to process the request. However, if the container was
made public with a Set Container ACL operation performed using version
2009-09-19 or newer, then the request is processed using version
2009-09-19.
Most likely you created the container or changed it's ACL before changing the service version and thus if no service version is provided, it is using the older version.
You can try two things:
Create a new blob container with ACL as public and try downloading a blob from there. Since the container is created with new service version, you should not encounter this error.
Change the container ACL to Private and then change it back to Public. Since the operation is now performed with the latest version of library (I'm assuming), you should not encounter this error when downloading blob.

How do I download documents from AtTask?

I'm working on a continuing API project. The current issue at hand is to be able to download my data from the AtTask server in precisely the folder structure they exist in on the AtTask servers. I've got the folder creation working nicely; the data types between Document, Document Folder and Document Version seem to be pretty clear. I am a little disillusioned about the fact that extension isn't in the document object (that I have to refer to the document VERSION for that)... but I can see some of the reason for that from a design perspective.
The issue I'm running into now is that I need to get the file content. I originally through from the API documentation that I'd be able to get to the file contents the same way as the documentation recommends uploading it -- through the handle. Unfortunately, neither document nor docv seem to support me accessing the handle except to write a new file.
So that leaves me the "download URL" as the remaining option. If I build the UI strings from the API calls using my browser, I get a URL with https://attaskURL/document/download?ID=xxxx (and can also get the versionID and such). If I paste the url into the browser where I'm logged in to the user interface of AtTask, it works fine and I can download the file. If, instead, I use my C# code to do so, I get the login page returned as a stream for me to download instead of my actual file because I'm not authenicated. I've tried creating a network credential and attaching it to the request with the username and password, but to no avail.
I imagine there's a couple ways to solve this problem -- the easy one being finding a way to "log in" to the download site through code (which doesn't seem to be the usual network credential object in C#) OR find a way to access the file contents through the API.
Appreciate your thoughts!
It looks like you can use the download URL if you put a session id in the URL. The details on getting a session id are here (basically just call login and a session id is returned in JSON):
http://developers.attask.com/api-docs/#Authentication
Then cram it on the end of your document download URL:
https://yourcompany.attask-ondemand.com/document/download?ID=xxxx&sessionID=abc1234
I've given this a quick test and I'm able to access a document.
You can use the downloadURL and a sessionID IF you are not using SAML authentication.
I have tried it both ways and using SAML will redirect you to the login page.

How to create usable URL for opening document?

The general problem: I have some code that needs a URL to a PDF file. It seems to work for URLs I find online, but not the ones I create myself.
For example, when I use a random URL from Xamarin it works fine, but when I try to generate a URL from either DropBox or Amazon Cloud Drive it does not work.
Example URLs:
These links open harmless PDF files. Please try it:
Xamarin (works fine)
DropBox (does not work)
Amazon Cloud Drive (does not work)
As you see, in a browser (I have used Chrome to test) you will get the PDF documents to open, but not without some kind of context (except for the Xamarin one).
The code: I am developing in MonoTouch and I am using a component called mTouch PDF Reader. The code is simply:
var documentViewController = new DocumentViewController (1, "Some name here", "http://someurlhere.pdf");
ActivateController (documentViewController);
This opens a nice PDF reader inside my app, but, as I can't use my own created URLs this does not help me. This is a 3rd party library so I can't look at the code. By the way, when I use one of my URLs, the code crashes with a System.NullReferenceException with this stacktrace:
MonoTouch.Foundation.NSArray.FromNativeObjects (items={MonoTouch.UIKit.UIViewController[1]}, count=1) in /Developer/MonoTouch/Source/monotouch/src/shared/Foundation/NSArray.cs:109
MonoTouch.Foundation.NSArray.FromNativeObjects (items={MonoTouch.UIKit.UIViewController[1]}) in /Developer/MonoTouch/Source/monotouch/src/shared/Foundation/NSArray.cs:96
MonoTouch.Foundation.NSArray.FromNSObjects (items={MonoTouch.UIKit.UIViewController[1]}) in /Developer/MonoTouch/Source/monotouch/src/shared/Foundation/NSArray.cs:48
MonoTouch.UIKit.UIPageViewController.SetViewControllers (viewControllers={MonoTouch.UIKit.UIViewController[1]}, direction=MonoTouch.UIKit.UIPageViewControllerNavigationDirection.Forward, animated=false, completionHandler={MonoTouch.UIKit.UICompletionHandler}) in /Developer/MonoTouch/Source/monotouch/src/UIKit/UIPageViewController.g.cs:144
mTouchPDFReader.Library.Views.Core.DocumentViewController.ViewDidLoad () in
MonoTouch.UIKit.UIApplication.UIApplicationMain () in
MonoTouch.UIKit.UIApplication.Main (args={string[0]}, principalClassName=(null), delegateClassName="AppDelegate") in /Developer/MonoTouch/Source/monotouch/src/UIKit/UIApplication.cs:38
Exam936.Application.Main (args={string[0]}) in /Users/EdGriMac/Dropbox/Quiz/Code/Exam926/Exam936/Main.cs:16
The frustration:
Is there a specific way to create URLs that work in this way? It does seem like DropBox does something different as it sort of iFrames the document or something. I don't know what Amazon Cloud Drive does. What has Xamarin done? Is it, as pointed out in the comments, because of http vs https?
I am completely lost. Am I missing something simple? Do you have any other way to create URLs to suggest? Googling this is really difficult as I continue to hit examples of how to share a URL in DropBox and so on...
By the way, I do not want to have the documents as part of the app as this means I will have to create a new version of the app just to change something in a document.
Update 1: I have added links above. I will try some other suggestions later and will leave more updates. Thanks in advance for any further suggestions!
Update 2: I have used Fiddler to look at the response on each of the URLs. The Xamarin URL has Content-Type: application/pdf while both DropBox and Amazon Cloud Drive has Content-Type: text/html; charset=UTF-8. This explains a lot. I will try andersr's suggestion later today as I do have a web server to put files on.
Update 3 When I put the PDF file on my Amazon EC2 server, created a virtual directory under my web site in IIS, the URL to my website + virtual directory + filename worked! Turns out the Content-Type had to be application/pdf for the mTouch PDF Reader to open it through a URL.
Thanks everyone for your help!
It seems to me that the first two URLS, link directly to the PDF files, but the latter one, ie. the one on Amazon Cloud Drive links to a page which again links to the PDF. I suggest the following potential solutions:
Find a reliable way to extract the direct url to the document on cloud drive. The link to the document is not the one you provided, but this: link . Perhaps Amazon has documentation on how you can avoid the html interface in order to retrive your file. I am not familiar with cloud drive at all. Note that the url provided has some time limited token attached to it.
Host the document on infrastructure you have more control over. IE. setup your own web server and host the documents there. Alternatively use another cloud storage provider which gives you the ability to link to files directly.

Categories

Resources