Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot download multiple OneDrive files concurrently since v.1.13.0-beta #413

Closed
tipa opened this issue Mar 26, 2019 · 47 comments · Fixed by #451
Closed

Cannot download multiple OneDrive files concurrently since v.1.13.0-beta #413

tipa opened this issue Mar 26, 2019 · 47 comments · Fixed by #451
Assignees
Labels

Comments

@tipa
Copy link

tipa commented Mar 26, 2019

Expected behavior

Until and including v1.12.0 I was able to download many files from OneDrive concurrently (see code snippet below) without any issues (and fast!).

Actual behavior

Since v1.13.0-beta (and incl. the now available v1.14.0) the download of multiple OneDrive files is slow from the beginning and is getting even slower over time. The app can only download up to ~15 files before the process eventually stops completely and the following exception is raised (no custom timeout set):

Code: generalExceptionMessage: An error occurred sending the request. ---> System.Net.Http.HttpRequestException: An error occurred while sending the request. ---> System.Exception: The text associated with this error code could not be found.The operation timed out at System.Net.Http.HttpHandlerToFilter.SendAsync(HttpRequestMessage request, CancellationToken cancel) at System.Net.Http.DiagnosticsHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) at System.Net.Http.HttpClientHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) --- End of inner exception stack trace --- at System.Net.Http.HttpClientHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) at Microsoft.Graph.AuthenticationHandler.SendAsync(HttpRequestMessage httpRequestMessage, CancellationToken cancellationToken) at Microsoft.Graph.RetryHandler.SendAsync(HttpRequestMessage httpRequest, CancellationToken cancellationToken) at Microsoft.Graph.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) at System.Net.Http.HttpClient.FinishSendAsyncBuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts) at Microsoft.Graph.HttpProvider.SendRequestAsync(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken) --- End of inner exception stack trace --- at Microsoft.Graph.HttpProvider.SendRequestAsync(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken) at Microsoft.Graph.HttpProvider.SendAsync(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken) at Microsoft.Graph.BaseRequest.SendRequestAsync(Object serializableObject, CancellationToken cancellationToken, HttpCompletionOption completionOption) at Microsoft.Graph.BaseRequest.SendStreamRequestAsync(Object serializableObject, CancellationToken cancellationToken, HttpCompletionOption completionOption) at Diarium.OneDriveHelper.DownloadFile(GraphServiceClient graphClient, String fileName)

Steps to reproduce the behavior

Microsoft.Graph v1.14.0
UWP app (but also happens in Xamarin)

var client = new GraphServiceClient("https://graph.microsoft.com/beta", new DelegateAuthenticationProvider(reqMsg =>
{
    reqMsg.Headers.Authorization = new AuthenticationHeaderValue("bearer", authResult.AccessToken);
    return Task.CompletedTask;
}));

SemaphoreSlim semaphore = new SemaphoreSlim(10);
if (filesToDownload.Count > 0)
{
    var downloadTasks = new List<Task>();
    var downloaded = 0; var error = false;
    foreach (var file in filesToDownload)
    {
        await semaphore.WaitAsync();
        if (error) { semaphore.Release(); break; }
        downloadTasks.Add(Task.Run(async () =>
        {
            try { file.Data = await DownloadFile(graphClient, file.Name); }
            catch { error = true; throw; }
            finally { semaphore.Release(); }
        }));
    }
    await Task.WhenAll(downloadTasks);
}


static async Task<byte[]> DownloadFile(GraphServiceClient graphClient, string fileName)
{
    using (var response = await graphClient.Drive.Special.AppRoot.ItemWithPath(fileName).Content.Request().GetAsync())
    {
        return Decrypt(response);
    }
}
@MIchaelMainer
Copy link
Contributor

Thank you for reporting this issue and providing repro steps.. We will investigate this.

@peombwa peombwa added the Bug label Mar 28, 2019
peombwa added a commit that referenced this issue Mar 28, 2019
@peombwa
Copy link
Member

peombwa commented Mar 29, 2019

@tipa, We have released a fix for this issue as part of release 1.14.1. Give it a try and let us know if it addresses your scenario.

@tipa
Copy link
Author

tipa commented Mar 29, 2019

I am struggling including the project into my solution. Would it be possible to release it on Nuget.org as a preview package or make the NuGet file available to me as a direct download?

@peombwa
Copy link
Member

peombwa commented Mar 29, 2019

@tipa Microsoft.Graph.Core 1.14.1 package is available on nuget.org. Just update the core package to 1.14.1.

@tipa
Copy link
Author

tipa commented Mar 29, 2019

I installed both packages via Nuget.org now:
image

Unfortunately, the issue was not resolved and the same error occurs. It looks like the library is receiving the download location (public.by.files.1drv.com....), but then doesnt send the GET request to that URL:
image

@darrelmiller
Copy link
Contributor

My reading of that trace is that request 53-59 + 62-63 are the initial requests that redirect with a 302 and then 66,67,70,71,etc are the corresponding GETs to the redirect location with response payload and .200.

Is there a reason you believe this is not the case?

@tipa
Copy link
Author

tipa commented Mar 30, 2019

No, this is absolutely correct. As I wrote in the first post, the first ~10-15 files are downloaded correctly. But you then see the requests in line 86 ff: They redirect to a different URL, but the library never sends a GET requests to them

@darrelmiller
Copy link
Contributor

@tipa My apologies, I missed that detail in your original post. I will continue to try to repro your issue. Could you try performing the multiple downloads by simply accumulating the tasks into an array and doing WaitAll and see if you still experience the problem. I'm assuming the semaphone/Task.Run/try/catch is a way of aborting all the tasks if one fails. If so you might be interested in this approach https://gist.github.com/svick/9992598 which uses a cancellation token to cancel all other tasks if one fails.

@darrelmiller
Copy link
Contributor

@tipa When just loading tasks into an array and doing WaitAll I am able to download 25 files without any issue or slowdown.
image

@darrelmiller
Copy link
Contributor

@tipa Do you have AppInsights enabled on your app? In the stacktrace I see a reference to DiagnosticsHandler and I suspect that might be coming from AppInsights.

@tipa
Copy link
Author

tipa commented Mar 31, 2019

Could you try performing the multiple downloads by simply accumulating the tasks into an array and doing WaitAll and see if you still experience the problem.

Tried that (I simply commented out the await semaphore.WaitAsync()) but then not even a single file (out of 748 in my test case) could be downloaded.
It might be worth noting that:

  • I am using ServicePointManager.DefaultConnectionLimit = 20; to increase the amount of max. concurrent HTTP calls. However I played around with multiple values and also commented out the line, but the problem persisted
  • All the files I am downloading are around 40-100KB in size
  • When I initialize the semaphore with 10, sometimes the app does download more than 25 files, up to maybe 40 - but then ultimately stops.
  • When I initialize the semaphore with 5, I was able to download way more files, but at a very slow pace. I stopped after 6 minutes with 160 files downloaded
  • When I initialize the semaphore with 1 (so no parallel downloads) it works better and I can download more files. However, even then the downloads slow down over time. After after 50 files it takes around 1.5 seconds for each file
  • In all the HTTP responses from public.by.files.1drv.com I see this header:
    WWW-Authenticate: Bearer realm="OneDriveAPI", error="invalid_token", error_description="Invalid auth token"

I'm assuming the semaphone/Task.Run/try/catch is a way of aborting all the tasks if one fails.

The main reason for using the sema is to only download 10 files at a time. Sometimes I need to download multiple hundreds or even thousands of files which would lead to timeout errors very quickly if I requested them all at once. The try-catch is for the case a task fails and to not make any additional requests. I don't think the semaphore is the cause of the issue here because it worked fine with v1.1.12 and with other cloud storage libraries I implemented (Google Drive, Dropbox, ...)

Do you have AppInsights enabled on your app

I am using AppCenter in my app

@MIchaelMainer
Copy link
Contributor

No, this is absolutely correct. As I wrote in the first post, the first ~10-15 files are downloaded correctly. But you then see the requests in line 86 ff: They redirect to a different URL, but the library never sends a GET requests to them

Can you share with us a capture of using 1.14.1 getting redirected but not sending the subsequent GET requests? Can you show us the same capture using 1.12 with the same settings?

@tipa
Copy link
Author

tipa commented Apr 1, 2019

It keeps picking up v1.14.0, perhaps because 1.14.0 fulfills the requirements of the Microsoft.Graph package. How do I force v1.14.1 of the Microsoft.Graph.Core package?
imageimage

@MIchaelMainer
Copy link
Contributor

Manage the Microsoft.Graph.Core NuGet and select Version 1.14.1 from the version drop down.

@tipa
Copy link
Author

tipa commented Apr 1, 2019

I have 1.14.1 selected:
image
Wouldn't it be possible to update the Microsoft.Graph package with 1.41.1 of Microsoft.Graph.Core as dependency? Or is there any setting to tell NuGet to always use the latest available dependency?

@MIchaelMainer
Copy link
Contributor

Yes, we can update Microsoft.Graph to use 1.14.1 of Core as the minimum dependency but then it forces an upgrade. We need to change packagereference to use a wildcard.

@tipa
Copy link
Author

tipa commented Apr 2, 2019

Seems like I am not the only one having that issue: #421 (comment)
Please let me know once you updated the Nuget packages so that it uses 1.14.1 for Core and I will test again if the issue was resolved

@whentotrade
Copy link

I am running into the same issue. Upgraded to version 1.14. and core 1.14.1 and onedrive download slows down and breaks with timout service request exception. What is the proposed solution?

@darrelmiller
Copy link
Contributor

@whentotrade Are you also using Task.Run to execute parrallel calls? Would you be able to provide a snippet of the code you are using for downloading files?

@whentotrade
Copy link

whentotrade commented Apr 23, 2019

@darrelmiller: Yes. Snipped below. The same code worked without any problem with 1.12. However with 1.14. the try/catch in the GetFileBytes function is raising the exception with "graph service exception" timeout somewhere around 100 files. The first files run smooth, then slows down and breaks.

Added note: Just running two tasks in parallel, not more.

var DownloadFileTask = Task.Run(async () =>
{
          return await GetFileBytes(fi);
});

public async Task<byte[]> GetFileBytes(DriveItem fileItem)
        {
            try
            {
                using (var stream = await this.graphClient.Drives[fileItem.ParentReference.DriveId].Items[fileItem.Id].Content.Request().GetAsync())
                using (var outputStream = new MemoryStream())
                {
                    await stream.CopyToAsync(outputStream);
                    return outputStream.ToArray();
                }

            }
            catch (Exception exception)
            {
                Trace.TraceWarning("----> error: could not download file via onedrivebusiness!");
                 //...
                return null;
                
            }

        }
``

@darrelmiller
Copy link
Contributor

@whentotrade Thanks, this is really helpful.

@whentotrade
Copy link

Here is the error log catched:

Microsoft.Graph.ServiceException: Code: timeout
Message: The request timed out.
---> System.Threading.Tasks.TaskCanceledException: Eine Aufgabe wurde abgebrochen.
bei System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
bei Microsoft.Graph.RedirectHandler.d__6.MoveNext()
--- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde ---
bei System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
bei System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
bei Microsoft.Graph.RetryHandler.d__10.MoveNext()
--- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde ---
bei System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
bei System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
bei Microsoft.Graph.AuthenticationHandler.d__16.MoveNext()
--- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde ---
bei System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
bei System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
bei System.Net.Http.HttpClient.d__58.MoveNext()
--- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde ---
bei System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
bei System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
bei Microsoft.Graph.HttpProvider.d__19.MoveNext()
--- Ende der internen Ausnahmestapelüberwachung ---
bei Microsoft.Graph.HttpProvider.d__19.MoveNext()
--- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde ---
bei System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
bei Microsoft.Graph.HttpProvider.d__18.MoveNext()
--- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde ---
bei System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
bei Microsoft.Graph.BaseRequest.d__34.MoveNext()
--- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde ---
bei System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
bei Microsoft.Graph.BaseRequest.d__32.MoveNext()
--- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde ---
bei System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
bei System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
bei Noggle.Indexing.Index.OneDriveBusiness.OneDriveBusinessProvider.d__42.MoveNext()

@peombwa
Copy link
Member

peombwa commented Apr 24, 2019

@whentotrade Are you experiencing this in a UWP or Xamarin?

@tipa
Copy link
Author

tipa commented Apr 24, 2019

I experienced the issue on all UWP + Xamarin.Android + Xamarin.iOS

@whentotrade
Copy link

UWP (WPF .NET with Desktop Bridge as UWP)

@peombwa
Copy link
Member

peombwa commented Apr 26, 2019

@tipa @whentotrade Thanks for the feedback. We've found what's causing the issue and we are currently working on a fix.

@peombwa
Copy link
Member

peombwa commented Apr 27, 2019

@tipa, @whentotrade We've released Microsoft.Graph.Core 1.15.0-preview.2 that should fix this issue. Give it a try and let us know if it addresses your scenario.

@peombwa peombwa reopened this Apr 27, 2019
@tipa
Copy link
Author

tipa commented Apr 27, 2019

Thanks! Can you please update the Microsoft.Graph nuget package so the issue described above does not happen?

@whentotrade
Copy link

using Graph 1.14 and Core 1.15.0-preview.2 for quick test: Problem solved, looks like issue is fixed. Thank you and keep up your good work and service!

@tipa
Copy link
Author

tipa commented Apr 27, 2019

@whentotrade How did you manage to force-use Core 1.15.0-preview.2 instead of 1.14?

@whentotrade
Copy link

whentotrade commented Apr 27, 2019

@tipa: Yes. I first just upgraded the Core manually to 1.15.0-preview.2 and afterwards I upgraded the Graph package to 1.14. This way the upgrade for the Graph didnt requested the Core dependency package and accepted the already available 1.15 alpha.2.

@tipa
Copy link
Author

tipa commented Apr 27, 2019

Thanks! But that sounds like it would grab 1.14 again after a project clean&rebuild...

Tried it anyways and the problem was not solved for me on Android.Xamarin. Not sure if it used 1.14 anyways, but the .dll in the \obj\Debug\90\android\assets folder indicated v.1.15

@whentotrade
Copy link

The issue is fixed for me using .NET WPF Desktop App with UWP.

Final question:
Is the combination of Graph 1.14 and Core 1.15 alpha.2 a valid scenario for a production release?

@darrelmiller
Copy link
Contributor

darrelmiller commented Apr 28, 2019

@whentotrade Yay! Great to hear your issue was resolved.

Using Microsoft.Graph 1.14 and Microsoft.Graph.Core 1.15.0-preview.2 is valid combination, although we don't recommend using any "preview" build in production. We expect to release a final version of 1.15 this week.

We are starting to allow the versions of the "service library" Microsoft.Graph that contains all the generated code, to diverge from the "core library". Currently the numbers are close so it looks like they should align. However, moving forward they will be released independently and versioned independently.

@tipa You should be able to update to the preview core package by doing

install-package Microsoft.Graph.Core -version 1.15.0-preview.2

Let us know if you contain to have problems.

@tipa
Copy link
Author

tipa commented Apr 30, 2019

It works on UWP, but not on Xamarin Android. Haven't tested it on Xamarin.iOS.
I am using these settings for HttpClient on Android:
image

@tipa
Copy link
Author

tipa commented May 2, 2019

Bug still present with v1.15.0 on Xamarin.Android & Xamarin.iOS

@MIchaelMainer
Copy link
Contributor

We are investigating this today.

@tipa
Copy link
Author

tipa commented May 23, 2019

Any updates?

@peombwa
Copy link
Member

peombwa commented May 24, 2019

@tipa We internally use HttpClientHandler and I believe it's not handling parallel requests as expected on Xamarin.Android and Xamarin.iOS. Try adding the following lines when initializing GraphServiceClient in your Xamarin.Android project. It simply swaps our internal HttpClientHandler with AndroidClientHandler.

// Use AndroidClientHandler as opposed to HttpClientHandler.
var innerHandler = new AndroidClientHandler { AllowAutoRedirect = false };
var pipeline = GraphClientFactory.CreatePipeline(GraphClientFactory.CreateDefaultHandlers(authProvider), innerHandler);

var graphClient = new GraphServiceClient(authProvider, new HttpProvider(pipeline, true, new Serializer()));

Alternatively, you can clone this sample that I've setup and run it against your test data and see if it works for your scenario.

@tipa
Copy link
Author

tipa commented May 24, 2019

That works for Android, but I am still having problems with iOS. My code looks like this now:

        static GraphServiceClient GetGraphClient(AuthenticationResult authResult)
        {
            var authProvider = new DelegateAuthenticationProvider(reqMsg =>
            {
                reqMsg.Headers.Authorization = new AuthenticationHeaderValue("bearer", authResult.AccessToken);
                return Task.CompletedTask;
            });
#if __ANDROID__
            var innerHandler = new Xamarin.Android.Net.AndroidClientHandler { AllowAutoRedirect = false };
            var pipeline = GraphClientFactory.CreatePipeline(GraphClientFactory.CreateDefaultHandlers(authProvider), innerHandler);
            var httpProvider = new HttpProvider(pipeline, true, new Serializer());
#elif __IOS__
            var innerHandler = new NSUrlSessionHandler { AllowAutoRedirect = false };
            var pipeline = GraphClientFactory.CreatePipeline(GraphClientFactory.CreateDefaultHandlers(authProvider), innerHandler);
            var httpProvider = new HttpProvider(pipeline, true, new Serializer());
#else // UWP
            IHttpProvider httpProvider = null;
#endif
            return new GraphServiceClient("https://graph.microsoft.com/beta", authProvider, httpProvider);
        }

I am getting this exception:

Microsoft.Graph.ServiceException: Code: generalException
Message: An error occurred sending the request.
---> System.IO.IOException: Corrupted data ReadInternal
at (wrapper managed-to-native) System.Object.__icall_wrapper_mono_delegate_end_invoke(object,intptr)
at (wrapper delegate-end-invoke) .end_invoke_int__this___IAsyncResult(System.IAsyncResult)
at System.IO.Compression.DeflateStream.EndRead (System.IAsyncResult asyncResult) [0x00044] in /Library/Frameworks/Xamarin.iOS.framework/Versions/12.8.0.2/src/Xamarin.iOS/mcs/class/System/System.IO.Compression/DeflateStream.cs:281
at System.IO.Stream+<>c.b__43_1 (System.IO.Stream stream, System.IAsyncResult asyncResult) [0x00000] in /Library/Frameworks/Xamarin.iOS.framework/Versions/12.8.0.2/src/Xamarin.iOS/mcs/class/referencesource/mscorlib/system/io/stream.cs:450
at System.Threading.Tasks.TaskFactory1+FromAsyncTrimPromise1[TResult,TInstance].Complete (TInstance thisRef, System.Func`3[T1,T2,TResult] endMethod, System.IAsyncResult asyncResult, System.Boolean requiresSynchronization) [0x00000] in /Library/Frameworks/Xamarin.iOS.framework/Versions/12.8.0.2/src/Xamarin.iOS/external/corert/src/System.Private.CoreLib/src/System/Threading/Tasks/FutureFactory.cs:1292
--- End of stack trace from previous location where exception was thrown ---

at System.IO.Stream.CopyToAsyncInternal (System.IO.Stream destination, System.Int32 bufferSize, System.Threading.CancellationToken cancellationToken) [0x000cf] in /Library/Frameworks/Xamarin.iOS.framework/Versions/12.8.0.2/src/Xamarin.iOS/mcs/class/referencesource/mscorlib/system/io/stream.cs:171
at System.Net.Http.HttpContent.LoadIntoBufferAsync (System.Int64 maxBufferSize) [0x00064] in /Users/builder/jenkins/workspace/xamarin-macios/xamarin-macios/external/mono/mcs/class/System.Net.Http/System.Net.Http/HttpContent.cs:146
at System.Net.Http.HttpClient.SendAsyncWorker (System.Net.Http.HttpRequestMessage request, System.Net.Http.HttpCompletionOption completionOption, System.Threading.CancellationToken cancellationToken) [0x0012a] in /Users/builder/jenkins/workspace/xamarin-macios/xamarin-macios/external/mono/mcs/class/System.Net.Http/System.Net.Http/HttpClient.cs:284
at Microsoft.Graph.HttpProvider.SendRequestAsync (System.Net.Http.HttpRequestMessage request, System.Net.Http.HttpCompletionOption completionOption, System.Threading.CancellationToken cancellationToken) [0x00089] in :0
--- End of inner exception stack trace ---
at Microsoft.Graph.HttpProvider.SendRequestAsync (System.Net.Http.HttpRequestMessage request, System.Net.Http.HttpCompletionOption completionOption, System.Threading.CancellationToken cancellationToken) [0x000dd] in :0
at Microsoft.Graph.HttpProvider.SendAsync (System.Net.Http.HttpRequestMessage request, System.Net.Http.HttpCompletionOption completionOption, System.Threading.CancellationToken cancellationToken) [0x0008b] in :0
at Microsoft.Graph.BaseRequest.SendRequestAsync (System.Object serializableObject, System.Threading.CancellationToken cancellationToken, System.Net.Http.HttpCompletionOption completionOption) [0x001c6] in :0
at Microsoft.Graph.BaseRequest.SendAsync[T] (System.Object serializableObject, System.Threading.CancellationToken cancellationToken, System.Net.Http.HttpCompletionOption completionOption) [0x0008b] in :0
at Microsoft.Graph.DriveItemRequest.GetAsync (System.Threading.CancellationToken cancellationToken) [0x00082] in <14e4d7e2ccbf45c6867ae94f3c0e89cd>:0

I am getting a similar exception on Android, when I initialize the AndroidClientHandler like this:
var innerHandler = new Xamarin.Android.Net.AndroidClientHandler { AllowAutoRedirect = false, AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip };

@peombwa
Copy link
Member

peombwa commented May 24, 2019

@tipa Thanks for the detailed log!
The exception is thrown because both GraphServiceClient and NSUrlSessionHandler handle Decompression out of the box and NSUrlSessionHandler doesn't provide an option to turn it off.

For now, in your iOS preprocessor directive, you can remove our default CompressionHandler when wiring up the HttpProvider as such until we provide a fix for this:

#elif __IOS__
            var innerHandler = new NSUrlSessionHandler { AllowAutoRedirect = false };
            var handlers = GraphClientFactory.CreateDefaultHandlers(authProvider);
            // Remove CompressionHandler from pipeline when using NSUrlSessionHandler.
            handlers.Remove(handlers.FirstOrDefault((h) => h.GetType().Equals(typeof(CompressionHandler)))); // We need to provide a method to remove handlers by type. 
            var pipeline = GraphClientFactory.CreatePipeline(handlers , innerHandler);
            httpProvider = new HttpProvider(pipeline, true, new Serializer());

With this change, i'm able to download all files in parallel without an exception. Let us if it works for you.

@tipa
Copy link
Author

tipa commented May 24, 2019

Yaaay, that made it work! Thanks a lot - finally I can use v1.15.0 in all 3 projects.
Any chance to integrate those workarounds into the library (or at least mention them in the docs). I am sure some other Xamarin devleopers are using this lib as well.

@peombwa
Copy link
Member

peombwa commented May 24, 2019

@tipa Awesome, I'm glad it worked!

Yes, we'll make these changes to our library and I've added them to our backlog via issues #481 and #482 .

I'll go ahead and close this issue since we now have a workaround/fix for it. Thanks for the feedback in resolving this issue.

@tipa
Copy link
Author

tipa commented Mar 23, 2020

@peombwa @darrelmiller I started buidling a Xamarin.macOS app recently and now experience this issue again. Would it be possible to also use NSUrlSession by default for macOS? Right only the native handlers are used for Android and iOS only: https://github.com/microsoftgraph/msgraph-sdk-dotnet-core/blob/ada45005494a1e274a3a7db5a167ab3e0bc3940a/src/Microsoft.Graph.Core/Requests/GraphClientFactory.cs#L217

@darrelmiller
Copy link
Contributor

@tipa That seems like a reasonable request. I'm guessing it would require adding in an extra platform check. If you had the time to make a PR to add this, I can get it merged. If not, I'll try and get a dev to make the fix before our next release. Unfortunately, most of our devs are tied up with other priorities at the moment.

@tipa
Copy link
Author

tipa commented Mar 23, 2020

I created this pull request here: microsoftgraph/msgraph-sdk-dotnet-core#99
Hope everything is correct, it's only my second ever PR - apparently some check failed, not sure if it's my fault...

@darrelmiller
Copy link
Contributor

@tipa Thank you. We will investigate the issue.

@ghost ghost locked as resolved and limited conversation to collaborators Feb 22, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants