CommunityToolkit / WindowsCommunityToolkit

The Windows Community Toolkit is a collection of helpers, extensions, and custom controls. It simplifies and demonstrates common developer tasks building .NET apps with UWP and the Windows App SDK / WinUI 3 for Windows 10 and Windows 11. The toolkit is part of the .NET Foundation.
https://docs.microsoft.com/windows/communitytoolkit/
Other
5.82k stars 1.37k forks source link

Error "Could not load file or assembly" for OneDriveService.Instance.RootFolderForMeAsync() #3097

Open zipswich opened 4 years ago

zipswich commented 4 years ago

Describe the bug

The following code had been working flawlessly for about 2 years until today when I updated a bunch of NuGet packages: oneDriveRootFolder = await OneDriveService.Instance.RootFolderForMeAsync(); Now, it throws the following exception:

Could not load file or assembly 'Microsoft.IdentityModel.Clients.ActiveDirectory.Platform, Version=3.13.7.964, Culture=neutral, PublicKeyToken=31bf3856ad364e35'. The system cannot find the file specified.

at Microsoft.Toolkit.Services.MicrosoftGraph.MicrosoftGraphService.<LoginAsync>d__54.MoveNext()
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)
at Microsoft.Toolkit.Services.MicrosoftGraph.MicrosoftGraphService.LoginAsync(String loginHint)
at Microsoft.Toolkit.Services.OneDrive.OneDriveService.<LoginAsync>d__32.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Toolkit.Services.OneDrive.OneDriveService.<RootFolderForMeAsync>d__33.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()

I understand OneDriveService is obsolete. Is this expected? I would love to have it working now while preparing to use Graph SDK to replace it.

Steps to Reproduce

Steps to reproduce the behavior: OneDriveService.ServicePlatformInitializer = new OneDriveServicePlatformInitializer(); OneDriveService.Instance.Initialize(App.ClientId, new string[] { "Files.ReadWrite.All" }); OneDriveStorageFolder oneDriveRootFolder = await OneDriveService.Instance.RootFolderForMeAsync();

Expected behavior

No error.

Screenshots

If applicable, add screenshots to help explain your problem.

Environment

NuGet Package(s): 
![image](https://user-images.githubusercontent.com/6095671/72170648-36c63f00-339f-11ea-9210-a6d8af705e16.png)

Package Version(s): 
6.0.0

Windows 10 Build Number:
- [ ] Fall Creators Update (16299)
- [ ] April 2018 Update (17134)
- [ ] October 2018 Update (17763)
- [x] May 2019 Update (18362)
- [ ] Insider Build (build number: )

App min and target version:
- [ ] Fall Creators Update (16299)
- [ ] April 2018 Update (17134)
- [ ] October 2018 Update (17763)
- [x] May 2019 Update (18362)
- [ ] Insider Build (xxxxx)

Device form factor:
- [x] Desktop
- [ ] Xbox
- [ ] Surface Hub
- [ ] IoT

Visual Studio 
- [ ] 2017 (version: )
- [x] 2019 (version: ) 
- [ ] 2019 Preview (version: )

Additional context

Add any other context about the problem here.

zipswich commented 4 years ago

Downgrade Microsoft.IdentityModel to 3.13.7.964, but get the following error: https://aka.ms/msal-net-3-breaking-changes

michael-hawker commented 4 years ago

@zipswich yeah, the recommended guidance is to use the Graph SDK, which it sounds like you're looking at.. We do have new preview helpers to make it easier to connect.

However, the existing libraries are built on older graph/msal libraries. I don't think there were many, if any, updates in the OneDriveService as we've moved to the new system built on-top of the official SDKs. If it's on the only toolkit package piece you're working with, I'd just stay on the old version for now until you switch to the Graph SDK.

zipswich commented 4 years ago

@michael-hawker I decided to embrace Graph which I need to do sooner or later. I am just so swamped now so that I hesitated at the beginning.
Unfortunate, the journey with Graph has been very rough so far. I have reached a point of no return, but it looks like the planned update of an app will be held for ann uncertain period of time until I figure out how to make Graph work.

zipswich commented 4 years ago

@michael-hawker I am finally making progress by using Microsoft.Toolkit.Graph.Controls 6.1.0-preview1 in lieu of the Graph SDK. I have got stuck at the last step: uploading a file with its stream. The Graph reference document gives a C# example of updating a file, but not uploading one. I tried to use PutAsync without luck. Could you point me to an example of uploading a file? I just need to see one line of code.

michael-hawker commented 4 years ago

@zipswich saw you posted on the docs repo, that's the right thing to do, especially when a sample is missing like that.

I don't have much first-hand experience with OneDrive for things like this, I'm taking a quick look, but indeed it's not super obvious.

zipswich commented 4 years ago

@michael-hawker After extensive search, trial & error, I have finally figured out how to upload a small file (< 4MB) and a large file (quite different calls). It is fairly easy with the beloved toolkit. I would love to contribute simple code snippets to the toolkit's document. Is there a quick and appropriate way to do it?

michael-hawker commented 4 years ago

Thanks @zipswich, sorry for the delay, for toolkit docs can be found here: https://github.com/MicrosoftDocs/WindowsCommunityToolkitDocs

Otherwise, you could also make a PR against the official graph docs as well.

zipswich commented 4 years ago

Let me post the code snippet here first in case someone searches for an example as I did:

try
{
    IProvider provider = ProviderManager.Instance.GlobalProvider;
    //Intialize provider
    ...

    BasicProperties bp = await storageFile.GetBasicPropertiesAsync();

    using (Stream localStream = await storageFile.OpenStreamForReadAsync())
    {
        Debug.WriteLine("Uploading to OneDrive file: " + storageFile.Name + " File Size (MB):" + ((float)bp.Size / (1024 * 1024)).ToString("0.00"));
        if (bp.Size > 4*1024*1024)
        {
            UploadSession uploadSession = await provider.Graph.Me.Drive
                .Items[diameraAlternativeRoll.Id]
                .ItemWithPath(sstorageFilef.Name)
                .CreateUploadSession()
                .Request()
                .PostAsync();

            //// 320 KB - It must be multiples of 320KB. Otherwise an exception will be thrown.  5MB is the default.
            int maxChunkSize = 320 * 1024; 
            ChunkedUploadProvider  chunkedUploadProvider = new ChunkedUploadProvider(uploadSession, provider.Graph, localStream, maxChunkSize);

            // Set up the chunk request necessities
            IEnumerable<UploadChunkRequest> chunkRequests = chunkedUploadProvider.GetUploadChunkRequests();
            byte[] abReadBuffer = new byte[maxChunkSize];
            List<Exception> listExceptions = new List<Exception>();
            DriveItem itemResult = null;

            //upload the chunks
            foreach (var request in chunkRequests)
            {
                // Send chunk request
                var result = await chunkedUploadProvider.GetChunkRequestResponseAsync(request, abReadBuffer, trackedExceptions);

                if (result.UploadSucceeded)
                {
                    itemResult = result.ItemResponse;
                }
            }

            // Check that upload succeeded
            if (itemResult == null)
            {
                Utility.ShowToast("Upload", "Uploading failed for file: " + storageFile.Name);
            }
        }
        else
        {
            DriveItem driveItemFile = new DriveItem
            {
                Name = storageFile.Name,
                File = new Microsoft.Graph.File
                {
                    MimeType = "image/jpeg",
                },
                AdditionalData = new Dictionary<string, object>()
                {
                    { "@microsoft.graph.conflictBehavior", "fail" }
                },
                Content = localStream

            };

            driveItemFile = await provider.Graph.Me.Drive
                .Items[diameraAlternativeRoll.Id]
                .ItemWithPath(storageFile.Name)
                .Content
                .Request()
                .PutAsync<DriveItem>(localStream);
        }
        Debug.WriteLine("Finished uploading to OneDrive file: " + storageFile.Name);
    }
}
catch (ServiceException se)
{
    //Probably related to Graph.
}
catch (Exception ex)
{

}
Kyaa-dost commented 4 years ago

@zipswich was this added in the doc?

zipswich commented 4 years ago

@Kyaa-dost Sorry I have not got a chance to do anything. I am not well versed in PR. 😀

michael-hawker commented 2 years ago

@shweaver-MSFT we should just validate how this scenario works with the new helpers in 7.1.

jackmcc08 commented 1 year ago

@zipswich thank you very much for the code you posted above, massively helpful for the task I was working on (uploading large files to SharePoint Document Libraries.

As a side note and for future users, ChunkedUploadProvider is now deprecated and I used LargeFileUploadTask, using the code example illustrated in this Microsoft Documentation: Link

zipswich commented 1 year ago

Thank you for the tip, @jackmcc08. I will update my code with LargeFileUploadTask accordingly.