Exemple #1
0
        /// <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 async 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));

            // Send the query
            IJsonValue response = await this.ReadAsync(query, parameters);

            // Get the first element in the response
            JsonObject obj = response.AsObject();

            if (obj == null)
            {
                JsonArray 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()).Stringify()));
            }

            return(obj);
        }
Exemple #2
0
        /// <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.</returns>
        public new async Task <T> LookupAsync(object id, IDictionary <string, string> parameters)
        {
            // TODO: At some point in the future this will be involved in our
            // caching story and relationships across tables via foreign
            // keys.

            IJsonValue value = await this.SendLookupAsync(id, parameters);

            return(MobileServiceTableSerializer.Deserialize <T>(value.AsObject()));
        }
        /// <summary>
        /// Gets a named value from an object.
        /// </summary>
        /// <param name="value">
        /// The object to check (though the type is IJsonValue so multiple
        /// calls to Get can be chained together).
        /// </param>
        /// <param name="name">The name of the value to lookup.</param>
        /// <returns>
        /// The value associated with the name, or null if the instance isn't
        /// an object or the name was not found.
        /// </returns>
        public static IJsonValue Get(this IJsonValue value, string name)
        {
            JsonObject obj = value.AsObject();
            IJsonValue val = null;

            if (obj != null)
            {
                obj.TryGetValue(name, out val);
            }
            return(val);
        }
        public void AsObject()
        {
            IJsonValue value = null;

            Assert.IsNull(value.AsObject());
            Assert.IsNull(JsonExtensions.Null().AsObject());
            Assert.IsNull(JsonValue.CreateStringValue("asdfafd").AsObject());
            Assert.IsNull(JsonValue.CreateNumberValue(2.0).AsObject());
            Assert.IsNull(JsonValue.CreateBooleanValue(true).AsObject());
            Assert.IsNull(new JsonArray().AsObject());
            JsonObject obj = new JsonObject();

            value = obj;
            Assert.AreEqual(obj, obj.AsObject());
            Assert.AreEqual(obj, value);
        }
Exemple #5
0
        /// <summary>
        /// Patch an object with the values returned by from the server.  Given
        /// that it's possible for the server to change values on an insert or
        /// update, we want to make sure the client object reflects those
        /// changes.
        /// </summary>
        /// <param name="original">The first instance.</param>
        /// <param name="updated">The second instance.</param>
        /// <returns>
        /// The first instance patched with values from the second.
        /// </returns>
        private static IJsonValue Patch(IJsonValue original, IJsonValue updated)
        {
            JsonObject originalObj = original.AsObject();
            JsonObject updatedObj  = updated.AsObject();

            if (originalObj != null && updatedObj != null)
            {
                foreach (KeyValuePair <string, JsonValue> property in updatedObj.GetPropertyValues())
                {
                    originalObj.SetNamedValue(property.Key, property.Value);
                }

                // TODO: Should we also delete any fields on the first object
                // that aren't also on the second object?  Is that a scenario
                // for scripts?
            }
            else
            {
                Debug.Assert(false, "Patch expects two JSON objects.");
            }

            return(original);
        }
        /// <summary>
        /// Patch an object with the values returned by from the server.  Given
        /// that it's possible for the server to change values on an insert or
        /// update, we want to make sure the client object reflects those
        /// changes.
        /// </summary>
        /// <param name="original">The first instance.</param>
        /// <param name="updated">The second instance.</param>
        /// <returns>
        /// The first instance patched with values from the second.
        /// </returns>
        private static IJsonValue Patch(IJsonValue original, IJsonValue updated)
        {
            JsonObject originalObj = original.AsObject();
            JsonObject updatedObj = updated.AsObject();
            if (originalObj != null && updatedObj != null)
            {
                foreach (KeyValuePair<string, JsonValue> property in updatedObj.GetPropertyValues())
                {
                    originalObj.SetNamedValue(property.Key, property.Value);
                }

                // TODO: Should we also delete any fields on the first object
                // that aren't also on the second object?  Is that a scenario
                // for scripts?
            }
            else
            {
                Debug.Assert(false, "Patch expects two JSON objects.");
            }

            return original;
        }
        /// <summary>
        /// Deserialize a JSON value into an instance.
        /// </summary>
        /// <param name="value">The JSON value.</param>
        /// <param name="instance">The instance to deserialize into.</param>
        /// <param name="ignoreCustomSerialization">
        /// A value to indicate whether or not custom serialization should be
        /// ignored if the instance implements
        /// ICustomMobileServiceTableSerialization.  This flag is used by
        /// implementations of ICustomMobileServiceTableSerialization that want
        /// to invoke the default serialization behavior.
        /// </param>
        public static void Deserialize(IJsonValue value, object instance, bool ignoreCustomSerialization)
        {
            if (value == null)
            {
                throw new ArgumentNullException("value");
            }
            else if (instance == null)
            {
                throw new ArgumentNullException("instance");
            }

            // If the instance implements
            // ICustomMobileServiceTableSerialization, allow it to handle its
            // own deserialization.
            if (!ignoreCustomSerialization)
            {
                ICustomMobileServiceTableSerialization custom = instance as ICustomMobileServiceTableSerialization;
                if (custom != null)
                {
                    custom.Deserialize(value);
                    return;
                }
            }

            // Get the Mobile Services specific type info
            SerializableType type = SerializableType.Get(instance.GetType());

            // Get the object to deserialize
            JsonObject obj = value.AsObject();

            if (obj == null)
            {
                throw new ArgumentException(
                          string.Format(
                              CultureInfo.InvariantCulture,
                              Resources.MobileServiceTableSerializer_Deserialize_NeedObject,
                              value.ValueType),
                          "value");
            }

            // Create a set of required members that we can remove from as we
            // process their values from the object.  If there's anything left
            // in the set after processing all of the values, then we weren't
            // given all of our required properties.
            HashSet <SerializableMember> requiredMembers =
                new HashSet <SerializableMember>(type.Members.Values.Where(m => m.IsRequired));

            // Walk through all of the members defined in the object and
            // deserialize them into the instance one at a time
            foreach (KeyValuePair <string, JsonValue> assignment in obj.GetPropertyValues().OrderBy(a => type.GetMemberOrder(a.Key)))
            {
                // Look up the instance member corresponding to the JSON member
                SerializableMember member = null;
                if (type.Members.TryGetValue(assignment.Key, out member))
                {
                    // Remove the member from the required list (does nothing
                    // if it wasn't present)
                    requiredMembers.Remove(member);

                    // Convert the property value into a CLR value using either
                    // the converter or a standard simple JSON mapping.  This
                    // will throw for JSON arrays or objects.  Also note that
                    // we'll still run the value returned from the converter
                    // through the ChangeType call below to make writing
                    // converters a little easier (but it should be a no-op
                    // for most folks anyway).
                    object propertyValue = null;
                    if (member.Converter != null)
                    {
                        propertyValue = member.Converter.ConvertFromJson(assignment.Value);
                    }
                    else if (!assignment.Value.TryConvert(out propertyValue))
                    {
                        throw new ArgumentException(
                                  string.Format(
                                      CultureInfo.InvariantCulture,
                                      Resources.MobileServiceTableSerializer_Deserialize_CannotDeserializeValue,
                                      assignment.Value.Stringify(),
                                      type.Type.FullName,
                                      member.MemberName),
                                  "value");
                    }

                    // Change the type of the value to the desired property
                    // type (mostly to handle things like casting issues) and
                    // set the value on the instance.
                    object convertedValue = TypeExtensions.ChangeType(propertyValue, member.Type);
                    member.SetValue(instance, convertedValue);
                }
            }

            // Ensure we were provided all of the required properties.
            if (requiredMembers.Count > 0)
            {
                throw new SerializationException(
                          string.Format(
                              CultureInfo.InvariantCulture,
                              Resources.MobileServiceTableSerializer_Deserialize_MissingRequired,
                              type.Type.FullName,
                              string.Join(", ", requiredMembers.Select(m => m.Name))));
            }
        }