/// <summary> /// Executes a request and transforms a 412 and 409 response to respective exception type. /// </summary> private async Task <JToken> TransformHttpException(MobileServiceSerializer serializer, Func <Task <JToken> > action) { try { return(await action()); } catch (MobileServiceInvalidOperationException ex) { if (ex.Response.StatusCode != HttpStatusCode.PreconditionFailed && ex.Response.StatusCode != HttpStatusCode.Conflict) { throw; } T item = default(T); try { item = serializer.Deserialize <T>(ex.Value); } catch { } if (ex.Response.StatusCode == HttpStatusCode.PreconditionFailed) { throw new MobileServicePreconditionFailedException <T>(ex, item); } else if (ex.Response.StatusCode == HttpStatusCode.Conflict) { throw new MobileServiceConflictException <T>(ex, item); } throw; } }
/// <summary> /// Inserts an <paramref name="instance"/> into the table. /// </summary> /// <param name="instance"> /// The instance to insert into the table. /// </param> /// <param name="parameters"> /// A dictionary of user-defined parameters and values to include in /// the request URI query string. /// </param> /// <returns> /// A task that will complete when the insert finishes. /// </returns> public async Task <JToken> InsertAsync(JObject instance, IDictionary <string, string> parameters) { if (instance == null) { throw new ArgumentNullException("instance"); } // Make sure the instance doesn't have an int id set for an insertion object id = MobileServiceSerializer.GetId(instance, ignoreCase: false, allowDefault: true); bool isStringIdOrDefaultIntId = id is string || MobileServiceSerializer.IsDefaultId(id); if (!isStringIdOrDefaultIntId) { throw new ArgumentException( string.Format( CultureInfo.InvariantCulture, Resources.MobileServiceTable_InsertWithExistingId, MobileServiceSerializer.IdPropertyName), "instance"); } parameters = AddSystemProperties(this.SystemProperties, parameters); string uriString = GetUri(this.TableName, null, parameters); MobileServiceHttpResponse response = await this.MobileServiceClient.HttpClient.RequestAsync(HttpMethod.Post, uriString, this.MobileServiceClient.CurrentUser, instance.ToString(Formatting.None), true); return(GetJTokenFromResponse(response)); }
/// <summary> /// Updates an instance in the table. /// </summary> /// <param name="instance"> /// The instance to update. /// </param> /// <param name="parameters"> /// A dictionary of user-defined parameters and values to include in /// the request URI query string. /// </param> /// <returns> /// A task that will complete when the update has finished. /// </returns> public async Task UpdateAsync(T instance, IDictionary <string, string> parameters) { if (instance == null) { throw new ArgumentNullException("instance"); } MobileServiceSerializer serializer = this.MobileServiceClient.Serializer; JObject value = serializer.Serialize(instance) as JObject; JToken updatedValue = null; try { updatedValue = await this.UpdateAsync(value, parameters); } catch (MobileServicePreconditionFailedException ex) { T item = default(T); try { item = serializer.Deserialize <T>(ex.Value); } catch { } throw new MobileServicePreconditionFailedException <T>(ex, item); } serializer.Deserialize <T>(updatedValue, instance); }
/// <summary> /// Refresh the current instance with the latest values from the /// table. /// </summary> /// <param name="instance"> /// The instance to refresh. /// </param> /// <param name="parameters"> /// A dictionary of user-defined parameters and values to include in /// the request URI query string. /// </param> /// <returns> /// A task that will complete when the refresh has finished. /// </returns> public async Task RefreshAsync(T instance, IDictionary <string, string> parameters) { if (instance == null) { throw new ArgumentNullException("instance"); } MobileServiceSerializer serializer = this.MobileServiceClient.Serializer; object id = serializer.GetId(instance, allowDefault: true); if (MobileServiceSerializer.IsDefaultId(id)) { return; } if (id is string) { MobileServiceSerializer.EnsureValidStringId(id, allowDefault: true); } // Get the latest version of this element JObject refreshed = await this.GetSingleValueAsync(id, parameters); // Deserialize that value back into the current instance serializer.Deserialize <T>(refreshed, instance); }
/// <summary> /// Updates an instance in the table. /// </summary> /// <param name="instance"> /// The instance to update. /// </param> /// <param name="parameters"> /// A dictionary of user-defined parameters and values to include in /// the request URI query string. /// </param> /// <returns> /// A task that will complete when the update has finished. /// </returns> public async Task UpdateAsync(T instance, IDictionary <string, string> parameters) { if (instance == null) { throw new ArgumentNullException("instance"); } MobileServiceSerializer serializer = this.MobileServiceClient.Serializer; object id = serializer.GetId(instance); if (serializer.IsDefaultId(id)) { throw new ArgumentException( string.Format( CultureInfo.InvariantCulture, Resources.MobileServiceTable_UpdateWithoutId, MobileServiceUrlBuilder.IdPropertyName), "instance"); } string value = serializer.Serialize(instance); string updatedValue = await this.SendUpdateAsync(id, value, parameters); serializer.Deserialize <T>(updatedValue, instance); }
/// <summary> /// Inserts a new instance into the table. /// </summary> /// <param name="instance"> /// The instance to insert. /// </param> /// <param name="parameters"> /// A dictionary of user-defined parameters and values to include in /// the request URI query string. /// </param> /// <returns> /// A task that will complete when the insertion has finished. /// </returns> public async Task InsertAsync(T instance, IDictionary <string, string> parameters) { if (instance == null) { throw new ArgumentNullException("instance"); } MobileServiceSerializer serializer = this.MobileServiceClient.Serializer; object id = serializer.GetId(instance); // Make sure the instance doesn't have an id set for an insertion if (!serializer.IsDefaultId(id)) { throw new ArgumentException( string.Format( CultureInfo.InvariantCulture, Resources.MobileServiceTable_InsertWithExistingId, MobileServiceUrlBuilder.IdPropertyName), "instance"); } string value = serializer.Serialize(instance); string insertedValue = await this.SendInsertAsync(value, parameters); serializer.Deserialize <T>(insertedValue, instance); }
/// <summary> /// Deletes an instance from the table. /// </summary> /// <param name="instance"> /// The instance to delete. /// </param> /// <param name="parameters"> /// A dictionary of user-defined parameters and values to include in /// the request URI query string. /// </param> /// <returns> /// A task that will complete when the delete has finished. /// </returns> public async Task DeleteAsync(T instance, IDictionary <string, string> parameters) { if (instance == null) { throw new ArgumentNullException("instance"); } MobileServiceSerializer serializer = this.MobileServiceClient.Serializer; object id = serializer.GetId(instance); if (serializer.IsDefaultId(id)) { throw new ArgumentException( string.Format( CultureInfo.InvariantCulture, Resources.MobileServiceTable_DeleteWithoutId, MobileServiceUrlBuilder.IdPropertyName), "instance"); } // Send the request await this.SendDeleteAsync(id, parameters); // Clear the instance id since it's no longer associated with that // id on the server (note that reflection is goodly enough to turn // null into the correct value for us). serializer.ClearId(instance); }
/// <summary> /// Inserts an <paramref name="instance"/> into the table. /// </summary> /// <param name="instance"> /// The instance to insert into the table. /// </param> /// <param name="parameters"> /// A dictionary of user-defined parameters and values to include in /// the request URI query string. /// </param> /// <param name="features"> /// Value indicating which features of the SDK are being used in this call. Useful for telemetry. /// </param> /// <returns> /// A task that will complete when the insert finishes. /// </returns> internal async Task <JToken> InsertAsync(JObject instance, IDictionary <string, string> parameters, MobileServiceFeatures features) { if (instance == null) { throw new ArgumentNullException("instance"); } // Make sure the instance doesn't have an int id set for an insertion object id = MobileServiceSerializer.GetId(instance, ignoreCase: false, allowDefault: true); bool isStringIdOrDefaultIntId = id is string || MobileServiceSerializer.IsDefaultId(id); if (!isStringIdOrDefaultIntId) { throw new ArgumentException( string.Format( CultureInfo.InvariantCulture, "Cannot insert if the {0} member is already set.", MobileServiceSystemColumns.Id), "instance"); } features = this.AddRequestFeatures(features, parameters); string uriString = GetUri(this.TableName, null, parameters); return(await this.TransformHttpException(async() => { MobileServiceHttpResponse response = await this.MobileServiceClient.HttpClient.RequestAsync(HttpMethod.Post, uriString, this.MobileServiceClient.CurrentUser, instance.ToString(Formatting.None), true, features: this.Features | features); return GetJTokenFromResponse(response); })); }
/// <summary> /// Inserts an <paramref name="instance"/> into the table. /// </summary> /// <param name="instance"> /// The instance to insert into the table. /// </param> /// <param name="parameters"> /// A dictionary of user-defined parameters and values to include in /// the request URI query string. /// </param> /// <returns> /// A task that will complete when the insert finishes. /// </returns> public async Task <JToken> InsertAsync(JObject instance, IDictionary <string, string> parameters) { if (instance == null) { throw new ArgumentNullException("instance"); } // Make sure the instance doesn't have an id set for an insertion MobileServiceSerializer serializer = this.MobileServiceClient.Serializer; object id = serializer.GetId(instance, true); if (!serializer.IsDefaultId(id)) { throw new ArgumentException( string.Format( CultureInfo.InvariantCulture, Resources.MobileServiceTable_InsertWithExistingId, MobileServiceUrlBuilder.IdPropertyName), "instance"); } string response = await this.SendInsertAsync(instance.ToString(), parameters); return(response.ParseToJToken()); }
/// <summary> /// Removes system properties from the passed in item /// </summary> /// <param name="item"> /// The item returned from the server /// </param> /// <param name="parameters"> /// A dictionary of user-defined parameters and values to include in /// the request URI query string. /// </param> /// <param name="version"> /// Set to the value of the version system property before it is removed. /// </param> /// <returns> /// An item that only contains normal fields and the requested system properties /// </returns> private JToken RemoveUnrequestedSystemProperties(JToken item, IDictionary <string, string> parameters, string version) { object id = null; if (item == null) { return(null); } MobileServiceSerializer.TryGetId(item as JObject, true, out id); if (id == null || MobileServiceSerializer.IsIntegerId(id)) { return(item); } var actualSystemProperties = GetRequestedSystemProperties(parameters); if (actualSystemProperties == MobileServiceSystemProperties.All) { return(item); } string ignoredVersion = null; var cleanedItem = MobileServiceSerializer.RemoveSystemProperties(item as JObject, out ignoredVersion, actualSystemProperties); if (version != null) { cleanedItem[MobileServiceSerializer.VersionSystemPropertyString] = GetValueFromEtag(version); } return(cleanedItem); }
/// <summary> /// Initializes a new instance of the MobileServiceTables class. /// </summary> /// <param name="tableName"> /// The name of the table. /// </param> /// <param name="client"> /// The <see cref="MobileServiceClient"/> associated with this table. /// </param> public MobileServiceTable(string tableName, MobileServiceClient client) : base(tableName, client) { this.queryProvider = new MobileServiceTableQueryProvider(); this.SystemProperties = client.Serializer.GetSystemProperties(typeof(T)); Type idType = client.Serializer.GetIdPropertyType <T>(throwIfNotFound: false); this.hasIntegerId = idType == null || MobileServiceSerializer.IsIntegerId(idType); }
/// <summary> /// Undeletes an <paramref name="instance"/> from the table. /// </summary> /// <param name="instance">The instance to undelete from the table.</param> /// <param name="parameters"> /// A dictionary of user-defined parameters and values to include in /// the request URI query string. /// </param> /// <returns>A task that will complete when the undelete finishes.</returns> public async Task UndeleteAsync(T instance, IDictionary <string, string> parameters) { Arguments.IsNotNull(instance, nameof(instance)); MobileServiceSerializer serializer = this.MobileServiceClient.Serializer; JObject value = serializer.Serialize(instance) as JObject; JToken updatedValue = await TransformHttpException(serializer, () => UndeleteAsync(value, parameters, MobileServiceFeatures.TypedTable)); serializer.Deserialize(updatedValue, instance); }
/// <summary> /// if id is of type string then it strips the system properties and adds version header. /// </summary> /// <returns>The header collection with if-match header.</returns> private Dictionary <string, string> StripSystemPropertiesAndAddVersionHeader(ref JObject instance, ref IDictionary <string, string> parameters, object id) { string version = null; instance = MobileServiceSerializer.RemoveSystemProperties(instance, out version); Dictionary <string, string> headers = AddIfMatchHeader(version); return(headers); }
/// <summary> /// Executes a lookup against a table. /// </summary> /// <param name="id"> /// The id of the instance to lookup. /// </param> /// <param name="parameters"> /// A dictionary of user-defined parameters and values to include in /// the request URI query string. /// </param> /// <param name="features"> /// Value indicating which features of the SDK are being used in this call. Useful for telemetry. /// </param> /// <returns> /// A task that will return with a result when the lookup finishes. /// </returns> internal async Task <JToken> LookupAsync(object id, IDictionary <string, string> parameters, MobileServiceFeatures features) { MobileServiceSerializer.EnsureValidId(id); features = this.AddRequestFeatures(features, parameters); string uriString = GetUri(this.TableName, id, parameters); MobileServiceHttpResponse response = await this.MobileServiceClient.HttpClient.RequestAsync(HttpMethod.Get, uriString, this.MobileServiceClient.CurrentUser, null, true, features : this.Features | features); return(GetJTokenFromResponse(response)); }
/// <summary> /// Executes a lookup against a table. /// </summary> /// <param name="id"> /// The id of the instance to lookup. /// </param> /// <param name="parameters"> /// A dictionary of user-defined parameters and values to include in /// the request URI query string. /// </param> /// <returns> /// A task that will return with a result when the lookup finishes. /// </returns> public async Task <JToken> LookupAsync(object id, IDictionary <string, string> parameters) { MobileServiceSerializer.EnsureValidId(id); parameters = AddSystemProperties(this.SystemProperties, parameters); string uriString = GetUri(this.TableName, id, parameters); MobileServiceHttpResponse response = await this.MobileServiceClient.HttpClient.RequestAsync(HttpMethod.Get, uriString, this.MobileServiceClient.CurrentUser, null, true); return(GetJTokenFromResponse(response)); }
/// <summary> /// Inserts a new instance into the table. /// </summary> /// <param name="instance"> /// The instance to insert. /// </param> /// <param name="parameters"> /// A dictionary of user-defined parameters and values to include in /// the request URI query string. /// </param> /// <returns> /// A task that will complete when the insertion has finished. /// </returns> public async Task InsertAsync(T instance, IDictionary <string, string> parameters) { Arguments.IsNotNull(instance, nameof(instance)); MobileServiceSerializer serializer = this.MobileServiceClient.Serializer; JObject value = serializer.Serialize(instance) as JObject; value = MobileServiceSerializer.RemoveSystemProperties(value, out string unused); JToken insertedValue = await TransformHttpException(serializer, () => InsertAsync(value, parameters, MobileServiceFeatures.TypedTable)); serializer.Deserialize(insertedValue, instance); }
/// <summary> /// Undeletes an <paramref name="instance"/> from the table. /// </summary> /// <param name="instance">The instance to undelete from the table.</param> /// <param name="parameters"> /// A dictionary of user-defined parameters and values to include in /// the request URI query string. /// </param> /// <returns>A task that will complete when the undelete finishes.</returns> public async Task UndeleteAsync(T instance, IDictionary <string, string> parameters) { if (instance == null) { throw new ArgumentNullException("instance"); } MobileServiceSerializer serializer = this.MobileServiceClient.Serializer; JObject value = serializer.Serialize(instance) as JObject; JToken updatedValue = await TransformHttpException(serializer, () => this.UndeleteAsync(value, parameters, MobileServiceFeatures.TypedTable)); serializer.Deserialize <T>(updatedValue, instance); }
/// <summary> /// Updates an <paramref name="instance"/> in the table. /// </summary> /// <param name="instance"> /// The instance to update in the table. /// </param> /// <param name="parameters"> /// A dictionary of user-defined parameters and values to include in /// the request URI query string. /// </param> /// <returns> /// A task that will complete when the update finishes. /// </returns> public async Task <JToken> UpdateAsync(JObject instance, IDictionary <string, string> parameters) { if (instance == null) { throw new ArgumentNullException("instance"); } MobileServiceInvalidOperationException error = null; object id = MobileServiceSerializer.GetId(instance); string version = null; if (!MobileServiceSerializer.IsIntegerId(id)) { instance = RemoveSystemProperties(instance, out version); } parameters = AddSystemProperties(this.SystemProperties, parameters); try { Dictionary <string, string> headers = null; string content = instance.ToString(Formatting.None); string uriString = GetUri(this.TableName, id, parameters); if (version != null) { headers = new Dictionary <string, string>(); headers.Add("If-Match", GetEtagFromValue(version)); } MobileServiceHttpResponse response = await this.MobileServiceClient.HttpClient.RequestAsync(patchHttpMethod, uriString, this.MobileServiceClient.CurrentUser, content, true, headers); return(GetJTokenFromResponse(response)); } catch (MobileServiceInvalidOperationException ex) { if (ex.Response != null && ex.Response.StatusCode != HttpStatusCode.PreconditionFailed) { throw; } error = ex; } JToken value = await this.ParseContent(error.Response); throw new MobileServicePreconditionFailedException(error, value); }
/// <summary> /// Deletes an instance from the table. /// </summary> /// <param name="instance"> /// The instance to delete. /// </param> /// <param name="parameters"> /// A dictionary of user-defined parameters and values to include in /// the request URI query string. /// </param> /// <returns> /// A task that will complete when the delete has finished. /// </returns> public async Task DeleteAsync(T instance, IDictionary <string, string> parameters) { Arguments.IsNotNull(instance, nameof(instance)); MobileServiceSerializer serializer = this.MobileServiceClient.Serializer; JObject value = serializer.Serialize(instance) as JObject; await TransformHttpException(serializer, () => DeleteAsync(value, parameters, MobileServiceFeatures.TypedTable)); // Clear the instance id since it's no longer associated with that // id on the server (note that reflection is goodly enough to turn // null into the correct value for us). serializer.SetIdToDefault(instance); }
/// <summary> /// Deletes an <paramref name="instance"/> from the table. /// </summary> /// <param name="instance"> /// The instance to delete from the table. /// </param> /// <param name="parameters"> /// A dictionary of user-defined parameters and values to include in /// the request URI query string. /// </param> /// <returns> /// A task that will complete when the delete finishes. /// </returns> public async Task <JToken> DeleteAsync(JObject instance, IDictionary <string, string> parameters) { if (instance == null) { throw new ArgumentNullException("instance"); } object id = MobileServiceSerializer.GetId(instance); parameters = AddSystemProperties(this.SystemProperties, parameters); string uriString = GetUri(this.TableName, id, parameters); MobileServiceHttpResponse response = await this.MobileServiceClient.HttpClient.RequestAsync(HttpMethod.Delete, uriString, this.MobileServiceClient.CurrentUser, null, false); return(GetJTokenFromResponse(response)); }
public async Task <U> InvokeApiAsync <T, U>(string apiName, T body, HttpMethod method, IDictionary <string, string> parameters, CancellationToken cancellationToken = default) { Arguments.IsNotNullOrWhiteSpace(apiName, nameof(apiName)); MobileServiceSerializer serializer = this.Serializer; string content = null; if (body != null) { content = serializer.Serialize(body).ToString(); } string response = await this.InternalInvokeApiAsync(apiName, content, method, parameters, MobileServiceFeatures.TypedApiCall, cancellationToken); if (string.IsNullOrEmpty(response)) { return(default);
/// <summary> /// Deletes an instance from the table. /// </summary> /// <param name="instance"> /// The instance to delete. /// </param> /// <param name="parameters"> /// A dictionary of user-defined parameters and values to include in /// the request URI query string. /// </param> /// <returns> /// A task that will complete when the delete has finished. /// </returns> public async Task DeleteAsync(T instance, IDictionary <string, string> parameters) { if (instance == null) { throw new ArgumentNullException("instance"); } MobileServiceSerializer serializer = this.MobileServiceClient.Serializer; JObject value = serializer.Serialize(instance) as JObject; await this.DeleteAsync(value, parameters); // Clear the instance id since it's no longer associated with that // id on the server (note that reflection is goodly enough to turn // null into the correct value for us). serializer.SetIdToDefault(instance); }
/// <summary> /// Inserts a new instance into the table. /// </summary> /// <param name="instance"> /// The instance to insert. /// </param> /// <param name="parameters"> /// A dictionary of user-defined parameters and values to include in /// the request URI query string. /// </param> /// <returns> /// A task that will complete when the insertion has finished. /// </returns> public async Task InsertAsync(T instance, IDictionary <string, string> parameters) { if (instance == null) { throw new ArgumentNullException("instance"); } MobileServiceSerializer serializer = this.MobileServiceClient.Serializer; JObject value = serializer.Serialize(instance) as JObject; string unused; value = MobileServiceSerializer.RemoveSystemProperties(value, out unused); JToken insertedValue = await TransformHttpException(serializer, () => this.InsertAsync(value, parameters, MobileServiceFeatures.TypedTable)); serializer.Deserialize <T>(insertedValue, instance); }
/// <summary> /// Invokes a user-defined custom API of a Windows Azure Mobile Service using the specified HTTP Method. /// Additional data can be sent though the HTTP content or the query string. /// </summary> /// <typeparam name="T">The type of instance sent to the Windows Azure Mobile Service.</typeparam> /// <typeparam name="U">The type of instance returned from the Windows Azure Mobile Service.</typeparam> /// <param name="apiName">The name of the custom API.</param> /// <param name="body">The value to be sent as the HTTP body.</param> /// <param name="method">The HTTP method.</param> /// <param name="parameters"> /// A dictionary of user-defined parameters and values to include in the request URI query string. /// </param> /// <returns>The response content from the custom api invocation.</returns> public async Task <U> InvokeApiAsync <T, U>(string apiName, T body, HttpMethod method, IDictionary <string, string> parameters) { if (string.IsNullOrWhiteSpace(apiName)) { throw new ArgumentNullException("apiName"); } MobileServiceSerializer serializer = this.Serializer; string content = null; if (body != null) { content = serializer.Serialize(body); } string response = await this.InternalInvokeApiAsync(apiName, content, method, parameters); return(serializer.Deserialize <U>(response)); }
/// <summary> /// Inserts a new instance into the table. /// </summary> /// <param name="instance"> /// The instance to insert. /// </param> /// <param name="parameters"> /// A dictionary of user-defined parameters and values to include in /// the request URI query string. /// </param> /// <returns> /// A task that will complete when the insertion has finished. /// </returns> public async Task InsertAsync(T instance, IDictionary <string, string> parameters) { if (instance == null) { throw new ArgumentNullException("instance"); } MobileServiceSerializer serializer = this.MobileServiceClient.Serializer; JObject value = serializer.Serialize(instance) as JObject; if (!this.hasIntegerId) { string unused; value = RemoveSystemProperties(value, out unused); } JToken insertedValue = await this.InsertAsync(value, parameters); serializer.Deserialize <T>(insertedValue, instance); }
/// <summary> /// Deletes an <paramref name="instance"/> from the table. /// </summary> /// <param name="instance"> /// The instance to delete from the table. /// </param> /// <param name="parameters"> /// A dictionary of user-defined parameters and values to include in /// the request URI query string. /// </param> /// <param name="features"> /// Value indicating which features of the SDK are being used in this call. Useful for telemetry. /// </param> /// <returns> /// A task that will complete when the delete finishes. /// </returns> internal async Task <JToken> DeleteAsync(JObject instance, IDictionary <string, string> parameters, MobileServiceFeatures features) { if (instance == null) { throw new ArgumentNullException("instance"); } object id = MobileServiceSerializer.GetId(instance); features = this.AddRequestFeatures(features, parameters); Dictionary <string, string> headers = StripSystemPropertiesAndAddVersionHeader(ref instance, ref parameters, id); string uriString = GetUri(this.TableName, id, parameters); return(await TransformHttpException(async() => { MobileServiceHttpResponse response = await this.MobileServiceClient.HttpClient.RequestAsync(HttpMethod.Delete, uriString, this.MobileServiceClient.CurrentUser, null, false, headers, this.Features | features); return GetJTokenFromResponse(response); })); }
/// <summary> /// Creates a collection of <see cref="JsonProperty"/> instances for the members of a given /// type. /// </summary> /// <remarks> /// This method is overridden in order to handle the id property of the type. Because multiple /// property names ("id" with different casings) are all treated as the id property, we must /// ensure that there is one and only one id property for the type. Also, the id property /// should be ignored when it is the default or null value and it should always serialize to JSON /// with a lowercase 'id' name. /// /// This method also checks for and applies and system property attributes. /// </remarks> /// <param name="type"> /// The type for which to create the collection of <see cref="JsonProperty"/> instances. /// </param> /// <param name="memberSerialization"> /// Specifies the member serialization options for the type. /// </param> /// <returns> /// A collection of <see cref="JsonProperty"/> instances for the members of a given /// type. /// </returns> protected override IList <JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization) { IList <JsonProperty> properties = base.CreateProperties(type, memberSerialization); // If this type is for a known table, ensure that it has an id. TypeInfo typeInfo = type.GetTypeInfo(); if (this.tableNameCache.ContainsKey(type) || this.tableNameCache.Keys.Any(t => t.GetTypeInfo().IsAssignableFrom(typeInfo))) { // Filter out properties that are not read/write properties = properties.Where(p => p.Writable).ToList(); // Find the id property JsonProperty idProperty = DetermineIdProperty(type, properties); bool isIntegerIdType = MobileServiceSerializer.IsIntegerId(idProperty); // Create a reverse cache of property to memberInfo to be used locally for validating the type Dictionary <JsonProperty, MemberInfo> memberInfoCache = new Dictionary <JsonProperty, MemberInfo>(); foreach (KeyValuePair <MemberInfo, JsonProperty> pair in jsonPropertyCache) { if (pair.Key.DeclaringType.GetTypeInfo().IsAssignableFrom(typeInfo)) { memberInfoCache.Add(pair.Value, pair.Key); } } // Set any needed converters and look for system property attributes foreach (JsonProperty property in properties) { SetMemberConverters(property); ApplySystemPropertyAttributes(property, memberInfoCache[property], isIntegerIdType); } // Determine the system properties from the property names // and add the system properties to the cache if (!isIntegerIdType) { AddSystemPropertyCacheEntry(type, properties); } } return(properties); }
/// <summary> /// Updates an <paramref name="instance"/> in the table. /// </summary> /// <param name="instance"> /// The instance to update in the table. /// </param> /// <param name="parameters"> /// A dictionary of user-defined parameters and values to include in /// the request URI query string. /// </param> /// <param name="features"> /// Value indicating which features of the SDK are being used in this call. Useful for telemetry. /// </param> /// <returns> /// A task that will complete when the update finishes. /// </returns> internal async Task <JToken> UpdateAsync(JObject instance, IDictionary <string, string> parameters, MobileServiceFeatures features) { if (instance == null) { throw new ArgumentNullException("instance"); } features = this.AddRequestFeatures(features, parameters); object id = MobileServiceSerializer.GetId(instance); Dictionary <string, string> headers = StripSystemPropertiesAndAddVersionHeader(ref instance, ref parameters, id); string content = instance.ToString(Formatting.None); string uriString = GetUri(this.TableName, id, parameters); return(await this.TransformHttpException(async() => { MobileServiceHttpResponse response = await this.MobileServiceClient.HttpClient.RequestAsync(patchHttpMethod, uriString, this.MobileServiceClient.CurrentUser, content, true, headers, this.Features | features); var result = GetJTokenFromResponse(response); return RemoveUnrequestedSystemProperties(result, parameters, response.Etag); })); }
/// <summary> /// Returns the id of the <paramref name="instance"/>. /// </summary> /// <param name="instance"> /// The instance that should have an id. /// </param> /// <returns> /// The id of the instance. /// </returns> /// <exception cref="ArgumentException"> /// Thrown if the <paramref name="instance"/> does not have an id. /// </exception> private object GetIdFromInstance(JObject instance) { Debug.Assert(instance != null); // Get the value of the object (as a primitive JSON type) MobileServiceSerializer serializer = this.MobileServiceClient.Serializer; object id = serializer.GetId(instance); if (serializer.IsDefaultId(id)) { throw new ArgumentException( string.Format( CultureInfo.InvariantCulture, Resources.MobileServiceTable_IdNotFound, MobileServiceUrlBuilder.IdPropertyName), "instance"); } return(id); }
/// <summary> /// Invokes a user-defined custom API of a Microsoft Azure Mobile Service using the specified HTTP Method. /// Additional data can be sent though the HTTP content or the query string. /// </summary> /// <typeparam name="T">The type of instance sent to the Microsoft Azure Mobile Service.</typeparam> /// <typeparam name="U">The type of instance returned from the Microsoft Azure Mobile Service.</typeparam> /// <param name="apiName">The name of the custom API.</param> /// <param name="body">The value to be sent as the HTTP body.</param> /// <param name="method">The HTTP method.</param> /// <param name="parameters"> /// A dictionary of user-defined parameters and values to include in the request URI query string. /// </param> /// <returns>The response content from the custom api invocation.</returns> public async Task <U> InvokeApiAsync <T, U>(string apiName, T body, HttpMethod method, IDictionary <string, string> parameters) { if (string.IsNullOrWhiteSpace(apiName)) { throw new ArgumentNullException("apiName"); } MobileServiceSerializer serializer = this.Serializer; string content = null; if (body != null) { content = serializer.Serialize(body).ToString(); } string response = await this.InternalInvokeApiAsync(apiName, content, method, parameters, MobileServiceFeatures.TypedApiCall); if (string.IsNullOrEmpty(response)) { return(default(U)); } return(serializer.Deserialize <U>(JToken.Parse(response))); }