/// <summary> /// Get an element from a table by its ID. /// </summary> /// <param name="id">The ID of the element.</param> /// <param name="parameters">A dictionary of user-defined parameters and values to include in the request URI query string.</param> /// <returns>The desired element as JSON object.</returns> private Task <JsonObject> GetSingleValueAsync(object id, IDictionary <string, string> parameters) { // Create a query for just this item string query = string.Format( CultureInfo.InvariantCulture, "$filter={0} eq {1}", MobileServiceTableUrlBuilder.IdPropertyName, TypeExtensions.ToODataConstant(id)); return(ReadAsync(query, parameters).ContinueWith(t => { // Get the first element in the response JsonObject obj = t.Result.AsObject(); if (obj == null) { JsonArray array = t.Result.AsArray(); if (array != null && array.Count > 0) { obj = array.FirstOrDefault().AsObject(); } } if (obj == null) { throw new InvalidOperationException( string.Format( CultureInfo.InvariantCulture, Resources.MobileServiceTables_GetSingleValueAsync_NotSingleObject, (t.Result ?? JsonExtensions.Null()).Stringify())); } return obj; })); }
/// <summary> /// Parse a JSON response into a sequence of elements and also return /// the count of objects. This method abstracts out the differences /// between a raw array response and an inline count response. /// </summary> /// <param name="response">The JSON response.</param> /// <param name="totalCount"> /// The total count as requested via the IncludeTotalCount method. /// </param> /// <returns>The response as a JSON array.</returns> internal static JsonArray GetResponseSequence(IJsonValue response, out long totalCount) { double?inlineCount = null; // Try and get the values as an array JsonArray values = response.AsArray(); if (values == null) { // Otherwise try and get the values from the results property // (which is the case when we retrieve the count inline) values = response.Get(InlineCountResultsKey).AsArray(); inlineCount = response.Get(InlineCountCountKey).AsNumber(); if (values == null) { throw new InvalidOperationException( string.Format( CultureInfo.InvariantCulture, Resources.MobileServiceTables_GetResponseSequence_ExpectedArray, (response ?? JsonExtensions.Null()).Stringify())); } } // Get the count via the inline count or default an unspecified // count to -1 totalCount = inlineCount != null ? (long)inlineCount.Value : -1L; return(values); }
/// <summary> /// Get an element from a table by its ID. /// </summary> /// <param name="id">The ID of the element.</param> /// <returns>The desired element as JSON object.</returns> private async Task <JObject> GetSingleValueAsync(object id) { // Create a query for just this item string query = string.Format( CultureInfo.InvariantCulture, "$filter={0} eq {1}", IdPropertyName, TypeExtensions.ToODataConstant(id)); // Send the query JToken response = await this.ReadAsync(query); // Get the first element in the response JObject obj = response.AsObject(); if (obj == null) { JArray array = response.AsArray(); if (array != null && array.Count > 0) { obj = array.FirstOrDefault().AsObject(); } } if (obj == null) { throw new InvalidOperationException( string.Format( CultureInfo.InvariantCulture, Resources.MobileServiceTables_GetSingleValueAsync_NotSingleObject, (response ?? JsonExtensions.Null()).ToString())); } return(obj); }
/// <summary> /// Set a named value on an object of any type. Unlike the other set /// overloads, this will attempt to convert arbitrary CLR values into /// the correct JSON types. /// </summary> /// <param name="obj">The object to set the value on.</param> /// <param name="name">The name of the value to set.</param> /// <param name="value">The value to set.</param> /// <returns>Whether we were able to set the value.</returns> public static bool TrySet(this JContainer obj, string name, object value) { Debug.Assert(obj != null, "obj should probably not be null!"); Debug.Assert(!string.IsNullOrEmpty(name), "name cannot be null or empty."); if (obj == null) { return(false); } if (value == null) { obj.Set(name, JsonExtensions.Null()); } else { // If the type is nullable, strip off the Nullable<> which will // allow the comparisons below to convert correctly (since // we've already checked the value isn't null) Type memberType = value.GetType(); memberType = Nullable.GetUnderlyingType(memberType) ?? memberType; RuntimeTypeHandle handle = memberType.TypeHandle; // Set the value based on the type for known primitives if (handle.Equals(typeof(bool).TypeHandle)) { obj.Set(name, Convert.ToBoolean(value, CultureInfo.InvariantCulture)); } else if (handle.Equals(typeof(int).TypeHandle) || handle.Equals(typeof(uint).TypeHandle) || handle.Equals(typeof(sbyte).TypeHandle) || handle.Equals(typeof(byte).TypeHandle) || handle.Equals(typeof(short).TypeHandle) || handle.Equals(typeof(ushort).TypeHandle) || handle.Equals(typeof(double).TypeHandle) || handle.Equals(typeof(float).TypeHandle) || handle.Equals(typeof(Decimal).TypeHandle) || handle.Equals(typeof(uint).TypeHandle)) { // Convert all numeric types into doubles obj.Set(name, Convert.ToDouble(value, CultureInfo.InvariantCulture)); } else if (handle.Equals(typeof(long).TypeHandle) || handle.Equals(typeof(ulong).TypeHandle)) { if (!NumericCanRoundtrip(value, memberType)) { throw new ArgumentOutOfRangeException( name, value, string.Format( Resources.JsonExtensions_TrySetValue_CannotRoundtripNumericValue, value, name, CultureInfo.InvariantCulture)); } obj.Set(name, Convert.ToDouble(value, CultureInfo.InvariantCulture)); } else if (handle.Equals(typeof(char).TypeHandle)) { // Convert characters to strings obj.Set(name, value.ToString()); } else if (handle.Equals(typeof(string).TypeHandle)) { obj.Set(name, value as string); } else if (handle.Equals(typeof(DateTime).TypeHandle)) { // Serialize DateTime as an ISO 8061 date/time obj.Set(name, ((DateTime)value).ToRoundtripDateString()); } else if (handle.Equals(typeof(DateTimeOffset).TypeHandle)) { // Serialize DateTimeOffset as an ISO 8061 date/time obj.Set(name, ((DateTimeOffset)value).DateTime.ToRoundtripDateString()); } else { return(false); } } return(true); }