Aug 11, 2014 Rajesh Guptha
In the recent build event, Microsoft announced a bunch of updates to its Azure stack. Today, I will focus on one of the most exciting features – Offline Sync on Mobile Services
As the name implies, it is an effort in the direction of providing out of the box offline sync capabilities for mobile applications which connect to Azure mobile services. Before this feature, one had to manually write all the plumbing code required to provide the seamless offline capabilities. Providing this out of the box feature will drastically reduce the time to market for many of the applications.
1. Backend services need to be hosted on Windows Azure mobile services. While this whole mobile service section is quite new on the stack, very few might be utilizing this service. For the new entrants on Azure, this can be an added services layer sitting right beside the existing WebAPI or WCF services which cater to the REST based requests. In fact Azure mobile services are heavily influenced by the Web API/MVC controller pattern.
2. SQLite DB is required on the device and nuget packages are available to create/access data from within the application. One can use Xamarin studios to develop cross platform native apps to utilize this feature also. Nuget packages for iOS, Android and WP are available to create and access SQLite database on all these platforms. In fact, these offline sync feature can be used in any windows application provided the above criteria holds good.
Microsoft.WindowsAzure.Mobile.Service.TableController<TableType>
where TableType is nothing but the entity/table that needs to be transferred back and forth between the device. The focus of this blog post shall be mainly on the offline sync capabilities, so let’s jump on to that.
var store = new MobileServiceSQLiteStore("store4.data");
store.DefineTable<TableType>();
Here [TableType] is the table that has shall contain some data which the user is expected to work with offline and sync later on. One can decide to have multiple such tables, but the lesser the better to avoid sync conflicts (explained later on).
this.client.SyncContext.InitializeAsync(store, new SyncHandler(this.client));
SyncContext is an implementation provided by the framework which monitors on the changes done during offline mode by the user. Hence, we need to initialize it specifying the store and a custom SyncHandler (explained later in the post).
var syncTable = this.client.GetSyncTable<TableType>();
syncTable.Someproperty = "Changed Value"; syncTable.UpdateAsync();
Synchronize with Server:
There are multiple steps involved to sync with the server for any offline changes performed.
Note: The key difference between all the method API’s explained above is Push changes is called on the SyncContext while purge and pull are on table basis. While it provides granular control over what operation to be performed, it would have been better if Microsoft would have provided an out of the box method of syncing data across.
Something on the lines of –
client.SyncContext.Synchronize();
Handling synchronization conflicts
Any synchronization comes with its own set of conflicts occurring while the sync process proceeds. There could be other clients connected to the server and updating related data in which case, when this user syncs data conflicts will occur. Remember we had provided a custom SyncHandler class while initializing the Sync Context.
This class has to implement IMobileServiceSyncHandler having two methods like:
public async Task<JObject> ExecuteTableOperationAsync(IMobileServiceTableOperation operation) { MobileServicePreconditionFailedException ex = null; JObject result = null; do { ex = null; try { result = await operation.ExecuteAsync(); } catch (MobileServicePreconditionFailedException e) { ex = e; } if (ex != null) { // There was a conflict in the server var serverItem = ex.Value; // Update the version of the pending item so that it won't have another // conflict when the operation is retried. operation.Item[MobileServiceSystemColumns.Version] = serverItem[MobileServiceSystemColumns.Version]; // One shall decide on a default action to be done in a conflict scenario. Server values override or client values overrides // The client can be shown with some sort of UI to let the end user decide on what has to be done with the conflicting record! // Finally, one has to update the final value to be updated in the server and re-do the ExecuteAsync operation. operation.Item["notes"] = MergeNotes(thisNotes, serverNotes); } } while (ex != null); return result; }
The above method shall be called for each and every row that the SyncContext identifies as a modified row. Potentially this method can be called concurrently for each row. Hence one should be careful in the logic of conflict resolution not to be dependent on associated rows.
public Task OnPushCompleteAsync(MobileServicePushCompletionResult result) { return Task.FromResult(0); }
As the name implies, this method shall be called once after the completion of pushing the data back on to the server. We can hook into this method to update the UI or anything similar if required.
So on the whole, this feature is quite exciting, enabling a lot of hard to implement scenarios right out of the box. There exists some room for improvements too, but given that this is still in alpha release, we can anticipate some more enhancements to this feature making it flawless in the future.
What do you think about this feature?
Is Microsoft going in the right direction?
Do share your comments
Dynamics 365 Human Resources Capabilities [11 Cool Features for Modern HR Teams]
Dec 13, 2024
What is Microsoft Power Pages? [Examples & Use Cases]
Oct 17, 2023
Expert Advice: Prerequisites for a Swift Migration from Salesforce to Dynamics 365
Oct 27, 2020
Rajesh Guptha is a prolific writer and content creator with over a decade of experience in the software development industry. Rajesh's writing style is characterized by a keen eye for detail, clarity, and precision.
We have plans which will meet your needs, and if not we can tweak them around a bit too!