This repository has been archived by the owner on Oct 27, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 259
/
SyncHandler.cs
106 lines (88 loc) · 3.91 KB
/
SyncHandler.cs
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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
using System;
using System.Diagnostics;
using System.Threading.Tasks;
using Microsoft.WindowsAzure.MobileServices;
using Microsoft.WindowsAzure.MobileServices.Sync;
using Newtonsoft.Json.Linq;
using Windows.UI.Popups;
namespace TodoOffline
{
public class SyncHandler : IMobileServiceSyncHandler
{
MobileServiceClient client;
const string LOCAL_VERSION = "Use local version";
const string SERVER_VERSION = "Use server version";
public SyncHandler(MobileServiceClient client)
{
this.client = client;
}
public virtual Task OnPushCompleteAsync(MobileServicePushCompletionResult result)
{
return Task.FromResult(0);
}
public virtual async Task<JObject> ExecuteTableOperationAsync(IMobileServiceTableOperation operation)
{
MobileServiceInvalidOperationException error;
Func<Task<JObject>> tryOperation = operation.ExecuteAsync;
do {
error = null;
try {
JObject result = await tryOperation();
return result;
}
catch (MobileServiceConflictException ex) {
error = ex;
}
catch (MobileServicePreconditionFailedException ex) {
error = ex;
}
catch (Exception e) {
Debug.WriteLine(e.ToString());
throw e;
}
if (error != null) {
var localItem = operation.Item.ToObject<TodoItem>();
var serverValue = error.Value;
if (serverValue == null) {
// 409 doesn't return the server item
serverValue = await operation.Table.LookupAsync(localItem.Id) as JObject;
}
var serverItem = serverValue.ToObject<TodoItem>();
if (serverItem.Complete == localItem.Complete && serverItem.Text == localItem.Text) {
// items are same so we can ignore the conflict
return serverValue;
}
IUICommand command = await ShowConflictDialog(localItem, serverValue);
if (command.Label == LOCAL_VERSION) {
// Overwrite the server version and try the operation again by continuing the loop
operation.Item[MobileServiceSystemColumns.Version] = serverValue[MobileServiceSystemColumns.Version];
if (error is MobileServiceConflictException) {
// change operation from Insert to Update
tryOperation = async () => await operation.Table.UpdateAsync(operation.Item) as JObject;
}
continue;
}
else if (command.Label == SERVER_VERSION) {
return (JObject)serverValue;
}
else {
operation.AbortPush();
}
}
} while (error != null);
return null;
}
private async Task<IUICommand> ShowConflictDialog(TodoItem localItem, JObject serverValue)
{
var dialog = new MessageDialog(
"How do you want to resolve this conflict?\n\n" + "Local item: \n" + localItem +
"\n\nServer item:\n" + serverValue.ToObject<TodoItem>(),
title: "Conflict between local and server versions");
dialog.Commands.Add(new UICommand(LOCAL_VERSION));
dialog.Commands.Add(new UICommand(SERVER_VERSION));
// Windows Phone not supporting 3 command MessageDialog
//dialog.Commands.Add(new UICommand("Cancel"));
return await dialog.ShowAsync();
}
}
}