dropbox-apimauidropbox-sdk

dot net maui and dropbox api: Error in call to API function "files/download"


I have visual studio 2022 and am using dot net maui building on the base example by James Montemagno. I am calling the dropbox api (visual studio package) to download a file and it works fine on windows, but when I switch to the android emulator I get this Error:

Error in call to API function "files/download":Bad HTTP "Content-Type" header: "application/x-www-form-urlencoded". Expecting one of "text/plain; charset=utf-8","application/octet-stream","application/octest-stream;charset=utf-8"

My code is very straightforward and listed below. I have googled this error and there were previous fixes but none seem to apply to the latest version of Visual Studio - hence the CreateClient()

using Dropbox.Api.Files;
using Dropbox.Api.Users;
public HttpClient CreateClient()
{
    #if __ANDROID__
        return new HttpClient(new Xamarin.Android.Net.AndroidMessageHandler());
    #else
        return new HttpClient();
    #endif
}
public async Task GetInfoFromDropbox()
{
    string szFileName = "Somefile.dat";
    string szDropBoxToken = "myDropboxToken";
    httpClient = CreateClient();
    var objDbx = new DropboxClient(szDropBoxToken, new DropboxClientConfig() { HttpClient = httpClient });

    // Code fails here      
    var result = await objDbx.Files.DownloadAsync(szFileName);

    // carries on working if windows
    var result2 = await result.GetContentAsStreamAsync();
}

Solution

  • I found the answer and it was a little more complicated than the supplied answer by user 21374054:

    I needed the conditional #if ANDROID as compiling for other platforms failed - otherwise the code is similar, BUT there was also a thread error which I resolved in the ReadDropbox routine

    so here is the code:

    #if __ANDROID__
    public class MyAndroidMessageHandler : Xamarin.Android.Net.AndroidMessageHandler
    {
        protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            if (request.RequestUri.AbsolutePath.Contains("files/download"))
            {
                request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
            }
            return base.SendAsync(request, cancellationToken);
        }
    }
    #endif
    
    public HttpClient CreateClient()
        {
    #if __ANDROID__
          return new HttpClient(new MyAndroidMessageHandler());
    #else
            return new HttpClient();
    #endif
        }
    
    public async Task<DataTable> ReadDropboxFile(string szFileName)
    {
        DataSet dataset = new DataSet();
        DataTable datatable = new DataTable();
        string szDropBoxToken = m_szDropBoxToken;
        httpClient = CreateClient();
        var objDbx = new DropboxClient(szDropBoxToken, new DropboxClientConfig() { HttpClient = httpClient });
    
        // this trick uses another thread to avoid an android error of using the main thread
        await Task.Run(async () => {
            var result = await objDbx.Files.DownloadAsync(szFileName);
            var result2 = await result.GetContentAsStreamAsync();
    
            dataset.ReadXml(result2);
        });
    
        datatable = dataset.Tables[0];
        return datatable;
    }