private async Task ProcessPutCommand(RestProcessParameters param, CancellationToken ct) { var restQuery = new RestQueryString(param); var entityDefinition = param.Model.EntitiesByPluralName.SafeGet(restQuery.Root); if (entityDefinition == null) { throw new BadRequestException($"Unable to find an entity definition named {restQuery.Root}."); } if (restQuery.AdditionalQualifier.IsNullOrEmpty()) { throw new BadRequestException($"A put request must apply to a specific id."); } var propertyBag = param.RequestSerializer.Deserialize(param.Context.Request.Body); propertyBag[MetaConstants.IdProperty] = restQuery.AdditionalQualifier; var entity = await EntityFactory.Hydrate(entityDefinition, propertyBag, ct); entity.Etag = param.Headers.IfNoneMatch(); var result = await EntityService.Update(entity, ct); Respond(param, result.ToPropertyBag(), StatusCodes.Status200OK, new Dictionary <string, string> { { WebConstants.ETagHeader, entity.Etag }, { WebConstants.LastModifiedHeader, result.LastModified.SelectOrDefault(x => x.ToUtcIso8601()) } }); }
private async Task ProcessDeleteCommand(RestProcessParameters param, CancellationToken ct) { var restQuery = new RestQueryString(param); var entityDefinition = param.Model.EntitiesByPluralName.SafeGet(restQuery.Root); if (entityDefinition == null) { throw new BadRequestException($"Unable to find an entity definition named {restQuery.Root}."); } if (restQuery.AdditionalQualifier.IsNullOrEmpty()) { throw new BadRequestException($"A delete request must include an id."); } var result = await EntityService.Delete(entityDefinition, restQuery.AdditionalQualifier, ct); if (!result) { Respond(param, new MessageResponse($"Unable to find a {entityDefinition.SingleName} with id {restQuery.AdditionalQualifier}."), StatusCodes.Status404NotFound); return; } Respond(param, null, StatusCodes.Status204NoContent); }
private async Task ProcessPostCommand(RestProcessParameters param, CancellationToken ct) { var restQuery = new RestQueryString(param); var entityDefinition = param.Model.EntitiesByPluralName.SafeGet(restQuery.Root); if (entityDefinition == null) { throw new BadRequestException($"Unable to find an entity definition named {restQuery.Root}."); } if (!restQuery.AdditionalQualifier.IsNullOrEmpty()) { throw new BadRequestException($"A post request should not have an additional qualifier."); } var propertyBag = param.RequestSerializer.Deserialize(param.Context.Request.Body); var entity = await EntityFactory.Create(entityDefinition, propertyBag, ct); var result = await EntityService.Create(entity, ct); Respond(param, result.ToPropertyBag(), StatusCodes.Status201Created, new Dictionary <string, string> { { WebConstants.ETagHeader, result.Etag }, { WebConstants.LastModifiedHeader, result.LastModified.SelectOrDefault(x => x.ToUtcIso8601()) }, { "Location", param.Context.Request.AbsoluteUri( $"{_options.Value.MountPoint}/{entityDefinition.Model.Name}/{entityDefinition.PluralName}/{WebUtility.UrlEncode(result.Id.ToString())}") } }); }
private async Task ProcessPatchCommand(RestProcessParameters param, CancellationToken ct) { var restQuery = new RestQueryString(param); var entityDefinition = param.Model.EntitiesByPluralName.SafeGet(restQuery.Root); if (entityDefinition == null) { throw new BadRequestException($"Unable to find an entity definition named {restQuery.Root}."); } if (restQuery.AdditionalQualifier.IsNullOrEmpty()) { throw new BadRequestException($"A patch request must apply to a specific id."); } if (!(param.RequestSerializer is JsonRestSerializer)) { throw new BadRequestException("Only JSON Patch is supported for patching resources."); } JsonPatchDocument jsonPatchDocument; try { jsonPatchDocument = HiveJsonSerializer.Instance.Deserialize <JsonPatchDocument>(param.Context.Request.Body); } catch (Exception ex) { throw new BadRequestException("Malformed JSON Patch.", ex); } var entity = await EntityService.GetById(entityDefinition, restQuery.AdditionalQualifier, ct); if (entity == null) { Respond(param, new MessageResponse($"Unable to find a {entityDefinition.SingleName} with id {restQuery.AdditionalQualifier}"), StatusCodes.Status404NotFound); return; } jsonPatchDocument.ApplyTo(entity, new EntityPatchObjectAdapter()); entity.Etag = param.Headers.IfNoneMatch(); var result = await EntityService.Update(entity, ct); Respond(param, result.ToPropertyBag(), StatusCodes.Status200OK, new Dictionary <string, string> { { WebConstants.ETagHeader, result.Etag }, { WebConstants.LastModifiedHeader, result.LastModified.SelectOrDefault(x => x.ToUtcIso8601()) } }); }
private static void FillOperators(IQuery query, RestQueryString restQuery, RestProcessParameters param) { if (restQuery.QueryStringValues.ContainsKey(RestConstants.LimitOperator)) { var maxResults = restQuery.QueryStringValues[RestConstants.LimitOperator].First().IntSafeInvariantParse(); query.SetMaxResults(maxResults); } if (restQuery.QueryStringValues.ContainsKey(RestConstants.OrderOperator)) { var orderby = restQuery.QueryStringValues[RestConstants.OrderOperator].FirstOrDefault(); var orderbyMatch = OrderByRegex.Match(orderby); if (orderbyMatch.Success) { switch (orderbyMatch.Groups["asc"].Value.IsNullOrEmpty() ? "asc" : orderbyMatch.Groups["asc"].Value) { case "asc": query.AddOrder(Order.Asc(orderbyMatch.Groups["prop"].Value)); break; case "desc": query.AddOrder(Order.Desc(orderbyMatch.Groups["prop"].Value)); break; } } } if (restQuery.QueryStringValues.ContainsKey(RestConstants.IncludeOperator)) { foreach (var value in restQuery.QueryStringValues[RestConstants.IncludeOperator]) { query.Include(value); } } if (restQuery.QueryStringValues.ContainsKey(RestConstants.SelectOperator)) { query.SetProjection(Projection.Properties(restQuery.QueryStringValues[RestConstants.SelectOperator])); } if (param.Context.Request.Headers.ContainsKey(RestConstants.ContinuationTokenHeader)) { var continuationToken = param.Context.Request.Headers[RestConstants.ContinuationTokenHeader].FirstOrDefault(); query.SetContinuationToken(continuationToken); } }
private IQuery CreateQuery(IEntityDefinition entityDefinition, RestQueryString restQuery, RestProcessParameters param) { var query = EntityService.CreateQuery(entityDefinition); foreach ( var queryStringValue in restQuery.QueryStringValues.Where(x => !x.Key.StartsWith(RestConstants.ReservedOperatorsPrefix))) { RecursiveFillQuery(query, null, queryStringValue.Key, queryStringValue.Value); } FillOperators(query, restQuery, param); if (restQuery.PathValues.Count == 0) { return(query); } if (restQuery.PathValues.Count > 1) { throw new BadRequestException("Multi-level query expressions in path is not supported."); } var pathValue = restQuery.PathValues.First(); var targetEntityDef = entityDefinition.Model.EntitiesByPluralName.SafeGet(pathValue.Key); if (targetEntityDef == null) { throw new NotFoundException($"Unable to find an entity definition named {pathValue.Key}"); } var targetPropertyDefinition = entityDefinition.Properties.SafeGet(targetEntityDef.SingleName); if (targetPropertyDefinition != null) { var subQuery = query.GetOrCreateSubQuery(targetPropertyDefinition.Name); RecursiveFillQuery(subQuery, null, MetaConstants.IdProperty, pathValue.Value); } return(query); }
private async Task ProcessQuery(RestProcessParameters param, CancellationToken ct) { var restQuery = new RestQueryString(param); var entityDefinition = param.Model.EntitiesByPluralName.SafeGet(restQuery.Root); if (entityDefinition == null) { throw new NotFoundException($"Unable to find an entity definition named {restQuery.Root}."); } if (!restQuery.AdditionalQualifier.IsNullOrEmpty()) { var result = await EntityService.GetById(entityDefinition, restQuery.AdditionalQualifier, ct); if (result == null) { Respond(param, new MessageResponse($"Unable to find a {entityDefinition.SingleName} with id {restQuery.AdditionalQualifier}"), StatusCodes.Status404NotFound); return; } var ifNoneMatch = param.Headers.IfNoneMatch(); if (string.Equals(ifNoneMatch, result.Etag, StringComparison.Ordinal)) { Respond(param, null, StatusCodes.Status304NotModified, new Dictionary <string, string> { { WebConstants.ETagHeader, result.Etag }, { WebConstants.LastModifiedHeader, result.LastModified.SelectOrDefault(x => x.ToUtcIso8601()) } }); } else { Respond(param, result.ToPropertyBag(), StatusCodes.Status200OK, new Dictionary <string, string> { { WebConstants.ETagHeader, result.Etag }, { WebConstants.LastModifiedHeader, result.LastModified.SelectOrDefault(x => x.ToUtcIso8601()) } }); } } else { var query = CreateQuery(entityDefinition, restQuery, param); if (query.MaxResults.HasValue) { var result = await query.ToContinuationEnumerable <IEntity>(ct); Respond(param, result.Select(x => x.ToPropertyBag()).ToArray(), StatusCodes.Status200OK, new Dictionary <string, string> { { RestConstants.ContinuationTokenHeader, result.ContinuationToken } }); } else { var result = await query.ToEnumerable <IEntity>(ct); Respond(param, result.Select(x => x.ToPropertyBag()).ToArray(), StatusCodes.Status200OK); } } }