Alyssa Strand
Alyssa Strand

Reputation: 3

UWP App With Azure Mobile Apps Backend Offline Data Sync Issue

I am developing a UWP app in C# that uses an Azure backend to sync from an Azure SQL Database to the local device SQLite database. This has worked fine since the initial implementation.

Now I am running into an issue when trying to sync larger images. Images smaller than ~ 3MB successfully convert from StorageFile to byte[] and are saved in the SQLite database and synced to the Azure DB. However, images larger than ~ 3MB have issues syncing. They will convert to byte[] and display properly, but the attempt to sync fails with this error:

"The HTTP request did not include a valid entity body. Please ensure there is an entity body and an associated Content-Type header present in the request."

On the server end, this manifests as a malformed syntax error.

All images are processed exactly the same. The web.config file has been altered to allow the requestLimits maxAllowedContentLength="2147483648". The column in the Azure database is set to varbinary(MAX).

This code calls the method to convert the selected file to byte[]:

byte[] image = await ImageUtils.ChooseImageFile();

Here is the conversion method:

public static async Task<byte[]> ChooseImageFile()
    {
        FileOpenPicker openPicker = new FileOpenPicker();
        openPicker.ViewMode = PickerViewMode.Thumbnail;
        openPicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
        openPicker.FileTypeFilter.Add(".jpg");
        openPicker.FileTypeFilter.Add(".jpeg");
        openPicker.FileTypeFilter.Add(".png");
        StorageFile file = await openPicker.PickSingleFileAsync();

        if (file == null)
            return null;

        byte[] bytes = null;
        using (var stream = await file.OpenReadAsync())
        {
            bytes = new byte[stream.Size];
            using (var reader = new DataReader(stream))
            {
                await reader.LoadAsync((uint)stream.Size);
                reader.ReadBytes(bytes);
            }
        }
        return bytes;
    }

The caller method then assigns the byte[] to the Image property of the entity.
On syncing, I am using the following method:

public async Task SyncOfflineCacheAsync()
    {
        try
        {
            await InitializeAsync();

            await _client.SyncContext.PushAsync();

            await PullTables();
        }
        catch (MobileServicePushFailedException ex)
        {
            if (ex.PushResult != null)
            {
                foreach (var error in ex.PushResult.Errors)
                {
                    await ResolveConflictAsync(error);
                }
            }
        }
    }

Which is where it fails on PushAsync() with the above error.

Is there some sort of implicit size limit for syncing images this way? I noticed the string representation of the byte[] displays as base64 for the larger images and hexadecimal for the smaller images, but I couldn't find any information on whether this is related to the issue. The byte[] itself appears to be correct.

Thank you!

Upvotes: 0

Views: 226

Answers (1)

Sunteen Wu
Sunteen Wu

Reputation: 10627

The web.config file has been altered to allow the requestLimits maxAllowedContentLength="2147483648".

maxAllowedContentLength specifies the maximum length of content in a request supported by IIS, whereas maxRequestLength indicates the maximum request size supported by ASP.NET, So you need to set both in order to upload large files: the smaller one "takes priority".

The default value of maxRequestLength is 4096 KB (4 MB), so that you may need to set this value as well.

<system.web>
  <compilation debug="true" targetFramework="4.7"/>
  <httpRuntime targetFramework="4.7" maxRequestLength="102400"/>
</system.web>

See this thread for more details.

Upvotes: 0

Related Questions