/// <summary> /// Deserialise the json returned from the connector and update the database with the parameters read /// </summary> /// <param name="json"></param> /// <returns></returns> public static string GetProjectDataFromJSON(string json) { try { //Parse JSON var settings = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore, StringEscapeHandling = StringEscapeHandling.EscapeHtml }; var projectRoot = JsonConvert.DeserializeObject <Project>(json, settings); DataDAO.ProcessJSON((Project)projectRoot); return("Data successfully downloaded"); } catch (Exception e) { Console.WriteLine(e); return("Error parsing data" + e); } }
/// <summary> /// Synchronises the specified project: Uploads data which do not yet exist on the server, then downloads all changes since the last synchronisation. /// This includes authorisation /// </summary> /// <param name="projectId"></param> public async static void SynchroniseDataForProject(string projectId) { //Refresh token, then synchronise var auth = Authentication.AuthParams; auth.ShowErrors = false; auth.AllowCancel = false; auth.Completed += async(sender, eventArgs) => { if (eventArgs.IsAuthenticated == true) { Dictionary <String, String> props = eventArgs.Account.Properties; Authentication.SaveTokens(props); string time = "0000-01-01T00:00:00"; var lastSync = DateTime.Now; DateTime.TryParse(time, out lastSync); var project = Project.FetchProject(projectId); if (project.lastSync != null) { lastSync = project.lastSync.ToUniversalTime(); time = lastSync.ToString("yyyy-MM-ddTHH:mm:ss" + "Z"); } var json = DataDAO.PrepareJSONForUpload(lastSync); // Prepare data for upload string url = App.ServerURL + "/api/Project/" + time + "?iamgod=true"; try { using (HttpClient client = new HttpClient()) { client.Timeout = TimeSpan.FromSeconds(6000); // 10 minutes var token = Preferences.Get("AccessToken", ""); client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token); MessagingCenter.Send(new DataDAO(), "SyncMessage", "Waiting for data"); var response = await client.PostAsync(url, new StringContent(json, Encoding.UTF8, "application/json")); //UPLOAD var jsonbytes = await response.Content.ReadAsByteArrayAsync(); var utf8 = Encoding.UTF8; var jsonResponse = utf8.GetString(jsonbytes, 0, jsonbytes.Length); //Response contains updates to data since last sync var settings = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore, StringEscapeHandling = StringEscapeHandling.EscapeHtml }; var returnedObject = JsonConvert.DeserializeObject <ProjectSyncDTO>(jsonResponse, settings); //Deserialise response if (returnedObject.success == true) { DataDAO.ProcessJSON(returnedObject.projectUpdate); //Update database with downloaded data using (SQLiteConnection conn = new SQLiteConnection(Preferences.Get("databaseLocation", ""))) { project.lastSync = DateTime.Now; conn.Update(project); var error = returnedObject.error; var deletedRecords = returnedObject.records.deleted; var deletedRecords2 = returnedObject.geometries.geometryRecords.deleted; var deletedRecordsTotal = deletedRecords.Concat(deletedRecords2).ToDictionary(kvp => kvp.Key, kvp => kvp.Value); var skippedRecords = returnedObject.records.skipped; var skippedRecords2 = returnedObject.geometries.geometryRecords.skipped; var skippedRecordsTotal = skippedRecords.Concat(skippedRecords2).ToDictionary(kvp => kvp.Key, kvp => kvp.Value); var deletedGeometries = returnedObject.geometries.deleted; var skippedGeometries = returnedObject.geometries.skipped; if (error == null || error == String.Empty) { error = "Data successfully downloaded"; } foreach (var deletedRecord in deletedRecordsTotal) { //Delete records from device which have been confirmed by the connector as 'deleted' in the central db var uid = deletedRecord.Key.ToString(); var queriedRec = conn.Table <Record>().Where(r => r.recordId == uid).FirstOrDefault(); conn.Delete(queriedRec, true); } foreach (var deletedGeometry in deletedGeometries) { //Delete geometries from device which have been confirmed by the connector as 'deleted' in the central db var uid = deletedGeometry.Key.ToString(); var queriedGeom = conn.Table <ReferenceGeometry>().Where(g => g.geometryId == uid).FirstOrDefault(); conn.Delete(queriedGeom, true); } foreach (var skippedGeom in skippedGeometries) { if (!skippedGeom.Value.Contains("Changes were made to the associated records")) { error = error + System.Environment.NewLine; error = error + skippedGeom.Key.ToString() + ", " + skippedGeom.Value; } } foreach (var skippedRec in skippedRecordsTotal) { error = error + System.Environment.NewLine; error = error + skippedRec.Key.ToString() + ", " + skippedRec.Value; } ShowSyncCompleteMessage(error); //Show any errors in the sync confirmation message } } } MessagingCenter.Send(new Project(), "DataDownloadError", "Data successfully synchronised"); App.SetProject(projectId); MessagingCenter.Send <Application, string>(Application.Current, "SyncMessage", ""); } catch (Exception e) { // Re Log in Console.WriteLine(e); MessagingCenter.Send(new Project(), "DataDownloadError", @"Error synchronising data"); App.Current.MainPage = Login.GetPageToView(); } } else { MessagingCenter.Send(new Project(), "DataDownloadError", @"Login failed"); } }; auth.Error += (sender, eventArgs) => { //Careful! This triggers on the iPhone even when login is successful }; await auth.RequestRefreshTokenAsync(Preferences.Get("RefreshToken", "")); }