public async Task<JObject> UploadUpdate(JObject item, Uri tableUri, IHttp http, IDictionary<string, string> parameters = null)
        {
            string version = null;
            JToken versionToken = item["__version"];
            if(versionToken != null)
            {
                version = versionToken.ToString();
            }
            else if(http.OriginalRequest != null)
            {
                EntityTagHeaderValue tag = http.OriginalRequest.Headers.IfMatch.FirstOrDefault();
                if (tag != null)
                {
                    //trim "
                    version = tag.Tag.Trim(new char[] { '"' });
                }
            }

            if(version == null)
            {
                throw new InvalidOperationException("Cannot update value without __version.");
            }

            //remove systemproperties
            JObject insertItem = item.Remove(prop => prop.Name.StartsWith("__"));

            string paramString = TimestampSynchronizer.GetQueryString(parameters);

            Uri updateUri = new Uri(string.Format("{0}/{1}{2}",
                tableUri.OriginalString,
                Uri.EscapeDataString(item["id"].ToString()),
                paramString != null ? "?" + paramString : string.Empty));

            HttpRequestMessage req = http.CreateRequest(new HttpMethod("PATCH"), updateUri, new Dictionary<string, string>() { { "If-Match", string.Format("\"{0}\"", version) } });
            req.Content = new StringContent(insertItem.ToString(Formatting.None), Encoding.UTF8, "application/json");

            try
            {
                JObject response = await http.GetJsonAsync(req);
                JArray results = ResponseHelper.GetResultsJArrayFromJson(response);
                IEnumerable<string> deleted = ResponseHelper.GetDeletedJArrayFromJson(response);

                string tableName = UriHelper.GetTableNameFromUri(tableUri);

                using (await this.storage.Open())
                {
                    await this.storage.StoreData(tableName, results);
                    await this.storage.RemoveStoredData(tableName, deleted);
                }

                return response;
            }
            catch(HttpStatusCodeException e)
            {
                if(e.StatusCode == HttpStatusCode.Conflict)
                {
                    Conflict c = JsonConvert.DeserializeObject<Conflict>(e.Message);
                    if(c != null)
                    {
                        this.OnConflict(c);
                        return ResponseHelper.CreateSyncResponseWithItems(c.CurrentItem, null);
                    }
                }
                return ResponseHelper.CreateSyncResponseWithItems(null, null);
            }
        }
        public async Task<JObject> UploadDelete(JObject item, Uri tableUri, IHttp http, IDictionary<string, string> parameters = null)
        {
            string paramString = TimestampSynchronizer.GetQueryString(parameters);
            Uri deleteUri = new Uri(string.Format("{0}/{1}?version={2}{3}", 
                tableUri.OriginalString, 
                Uri.EscapeDataString(item["id"].ToString()), 
                Uri.EscapeDataString(item["__version"].ToString()),
                paramString != null ? "&" + paramString : string.Empty));

            HttpRequestMessage req = http.CreateRequest(HttpMethod.Delete, deleteUri);

            try
            {
                JObject response = await http.GetJsonAsync(req);
                JArray results = ResponseHelper.GetResultsJArrayFromJson(response);
                IEnumerable<string> deleted = ResponseHelper.GetDeletedJArrayFromJson(response);

                string tableName = UriHelper.GetTableNameFromUri(tableUri);

                using (await this.storage.Open())
                {
                    await this.storage.StoreData(tableName, results);
                    await this.storage.RemoveStoredData(tableName, deleted);
                }

                return response;
            }
            catch (HttpStatusCodeException e)
            {
                if (e.StatusCode == HttpStatusCode.Conflict)
                {
                    Conflict c = JsonConvert.DeserializeObject<Conflict>(e.Message);
                    if (c != null)
                    {
                        this.OnConflict(c);
                        return ResponseHelper.CreateSyncResponseWithItems(null, c.CurrentItem["id"]);
                    }
                }
                return ResponseHelper.CreateSyncResponseWithItems(null, null);
            }
        }
        public async Task<JObject> UploadInsert(JObject item, Uri tableUri, IHttp http, IDictionary<string, string> parameters = null)
        {
            //remove systemproperties
            JObject insertItem = item.Remove(prop => prop.Name.StartsWith("__"));

            string paramString = TimestampSynchronizer.GetQueryString(parameters);

            Uri insertUri = new Uri(string.Format("{0}{1}",
                tableUri.OriginalString,
                paramString != null ? "?" + paramString : string.Empty));

            HttpRequestMessage req = http.CreateRequest(HttpMethod.Post, insertUri);
            req.Content = new StringContent(insertItem.ToString(Formatting.None), Encoding.UTF8, "application/json");

            JObject response = await http.GetJsonAsync(req);
            JArray results = ResponseHelper.GetResultsJArrayFromJson(response);
            IEnumerable<string> deleted = ResponseHelper.GetDeletedJArrayFromJson(response);

            string tableName = UriHelper.GetTableNameFromUri(tableUri);

            using (await this.storage.Open())
            {
                await this.storage.StoreData(tableName, results);
                await this.storage.RemoveStoredData(tableName, deleted);
            }

            return response;
        }