Pain points of Xamarin.Forms using Azure Mobile Apps offline sync feature

Background

In recent years, it becomes more and more common that enterprises are tranferring their websites to mobile apps. By transferring, I mean that they want both versions of their apps. That will give us a scenario that our users, especially for Microsoft customers, they will want a same database structure even a same set of Web API to use for both Website and mobile apps.

This blog is exactly the same situation here. I got one customer who already has a website and its Web API is based on .NET Core 2.0. However, he’s trying to use the Xamarin.Forms to build an app and also using the Azure Mobile Apps SDK to enable the offline sync feature in his app.

Of course, he wants the Web API to be the same for both Website and Mobile app.

What is Offline Sync?

If you use a mobile app, you will be handling data sync with the database. When the network is good on your mobile, you will never meet issue to query/add/update/delete from database and sync back with your mobile app.

However, you will never be confident that your mobile will always be under a good network situation. That’s where the offline sync fit in.

Offline sync allows users to interact with a mobile application, viewing, adding, or modifying data, even where there isn’t a network connection. Changes are stored in a local database, and once the device is online, the changes can be synced with the Azure Mobile Apps instance. This article explains how to add offline sync functionality to a Xamarin.Forms application.

How does offline sync with Xamarin and Azure mobile app SDK?

It’s actually quite easy to do so. If you are only dealing with the mobile app. You can directly use the Quick Start template from our Azure portal. It’s a todoList app that can be directly run and can be easily enabled for offline sync feature.

  1. Follow Create a Xamarin.Forms app with Azure to download the Xamarin.Forms app with Azure Mobile Apps SDK integrated.

  2. Follow Enable offline sync for your Xamarin.Forms mobile app to enable the offline sync feature in the project you just downloaded.

  3. Follow Synchronizing Offline Data with Azure Mobile Apps to understand the usage, troubleshooting and testing on offline sync feature.

If you followed these instructs and also if you are using the template that you downloaded from Azure portal, you will not see any problem at all. It’s working normally.


What is the issue?

As I mentioned in the above, if you purely run from our template, it will work. However, my customer is trying to use the same Web API to do the offline sync with the backend database, that’s where the issue came in.

Symptom

If you read in detail from the above document in step 3, you will find that the key code block for offline sync is the PushAsync() method which is within the SyncAsync() method.

Detail code as below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public async Task SyncAsync()
{
ReadOnlyCollection<MobileServiceTableOperationError> syncErrors = null;

try
{
// Call from the Azure Mobile Apps SDK
await this.client.SyncContext.PushAsync();

// The first parameter is a query name that is used internally by the client SDK to implement incremental sync.
// Use a different query name for each unique query in your program.
await this.todoTable.PullAsync("allTodoItems", this.todoTable.CreateQuery());
}
catch (MobileServicePushFailedException exc)
{
if (exc.PushResult != null)
{
syncErrors = exc.PushResult.Errors;
}
}

// Simple error/conflict handling.
if (syncErrors != null)
{
foreach (var error in syncErrors)
{
if (error.OperationKind == MobileServiceTableOperationKind.Update && error.Result != null)
{
// Update failed, revert to server's copy
await error.CancelAndUpdateItemAsync(error.Result);
}
else
{
// Discard local change
await error.CancelAndDiscardItemAsync();
}

Debug.WriteLine(@"Error executing sync operation. Item: {0} ({1}). Operation discarded.", error.TableName, error.Item["id"]);
}
}
}

And wala, my customer is getting error and he debugged the error in the foreach loop. The error is something like: [0:] Error executing sync operation. Item: WorkDiary (fcddf2b4a5c24e8b8119be2fd3af993c). Operation discarded..

Screenshot:

Sally port

This is the main content I want to share in this blog. The way I troubleshoot the issue and how I found the root cause is really important. You will not see much debugging or something because customer already knows how to get the error, and in this case, it’s also customer’s debugging leads us to the solution and root cause.

I was really lost when I first troubleshoot on this issue. I reviewed all the customer’s code related to the offline sync, and nothing suspecious coming out. Customer is following our documents and the code has barely been changed.

However, my customer has implemented one LoggingHandler() to capture logs for the web request he has made. And below is the content for his web request when calling PushAsync():

1
2
3
4
5
6
7
8
9
10
[0:] Request: POST https://xxxxxxxx.azurewebsites.net/tables/WorkDiary
[0:] {"id":"4aa5928a2486404b8e214c82c3a2219a","Company":"default_co","DriverName":"default_driver","Password":"default_pwrd","Vehicle":"default_veh","Fatigue":"default_fat","State":"Start Work","Time":"2018-07-18T00:05:19.492Z","Hour":0,"Min":0,"Anno":"default_anno","Comment":"default_comment"}
[0:] HEADERS
[0:] X-ZUMO-FEATURES:TU,OL
[0:] X-ZUMO-INSTALLATION-ID:07631a2a-dbfd-4965-ad35-3efeb57de7ae
[0:] Accept:application/json
[0:] User-Agent:ZUMO/4.0 (lang=Managed; os=Android; os_version=8.1.0; arch=Unix; version=4.0.2.0)
[0:] X-ZUMO-VERSION:ZUMO/4.0 (lang=Managed; os=Android; os_version=8.1.0; arch=Unix; version=4.0.2.0)
[0:] ZUMO-API-VERSION:2.0.0
[0:] Response: NotFound

We can learn from the above information that the data (json format) was there, the URL is clear, and the response status should be 404 Not Found.

Troubleshooting

After getting the information from customer, it suddenly hit me that since customer mentioned he’s trying to use the same Web API as his website, so is it really the same in these 2 scenarios?

One easy way to find out is: Fiddler to capture the network trace.

Below are the detail steps to troubleshoot the issue:

  1. I simulate the same process using Fiddler’s Composer feature. I built the same data in json format, I use POST method to post the data to the Web API Url.

    I got the same result as his Xamarin app, it returns 404 Not Found error:

  2. I created a record in customer’s website, while doing this, I captured the fiddler as below:

    And the data posted to the Web URL is:

From the above comparasion of the Fiddler trace, we can see at least 2 things:

  1. The Web URLs for the Web API that we are calling are totally different between customer’s website and Xamarin web request.
  2. In his website’s Web API, he’s using the Web Form data structure. However, in Azure Mobile Apps SDK, he’s using the json format.

So these are the root cause of why this issue is happening.

Solution (Pain Point)

Knowing the root cause, I went for product team in Microsoft for help. As product team mentioned, to use the Azure Mobile App SDK, customer has to implement the Web API according to the way that our SDK is trying to do.

It’s really bad because customer already implemented one Web API based on .NET Core, and our Azure Mobile SDK only supports .NET4.6. That’s why I am calling it the pain point because customer has no other way to avoid this issue.

Finally customer agreed to implement another set of API for this usage and I helped him with another case, and now I can confirm after implementing the API, it’s working as normal again.

Reference Links:

If you want to know details about developing Xamarin.Forms app using Azure Mobile SDK, here is the link you should definitely look into: Develop Cloud Connected Mobile Apps with Xamarin and Microsoft Azure

How to make icons to show for Secondary ToolbarItem in Xamarin.Forms
You need to set install_url to use ShareThis. Please set it in _config.yml.

Comments

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×