Пример #1
0
 public override void CreateResource(HttpRequestMessage request, ResourceRootSingle resource)
 {
     foreach (var httpRequestModifier in HttpRequestModifiers)
     {
         httpRequestModifier.CreateResource(request, resource);
     }
 }
Пример #2
0
        public async Task Update <TModel>(TModel model)
        {
            // guard from kunckleheads
            if (model == null)
            {
                throw new ArgumentNullException(nameof(model));
            }
            ThrowIfUnmanaged(model);

            var patch = BuildPatch(model);

            // if nothing was updated, no need to continue
            if (patch == null)
            {
                return;
            }

            var allModels = ModelRegistry.IncludedModelsCreate(model);

            foreach (var newModel in allModels)
            {
                var newResource = BuildModelResource(newModel);
                // Update the model instance in the argument
                var initialize = newModel.GetType().GetInitializeMethod();
                initialize.Invoke(newModel, new object[] { newResource, this });
            }

            var includes = allModels.Select(ModelRegistry.GetResource).ToArray();

            var originalResource = ModelRegistry.GetResource(model);

            var root    = ResourceRootSingle.FromResource(patch, includes);
            var request = await HttpRequestBuilder.UpdateResource(originalResource, root);

            var response = await HttpClient.SendAsync(request).ConfigureAwait(false);

            HttpResponseListener.UpdateResource(response.StatusCode, originalResource, root);
            response.CheckStatusCode();

            if (response.StatusCode == HttpStatusCode.OK)
            {
                var responseRoot = await response.GetContentModel <ResourceRootSingle>(JsonSettings);

                // Update the model instance in the argument
                var initialize = typeof(TModel).GetInitializeMethod();
                initialize.Invoke(model, new object[] { responseRoot.Data, this });
                Cache.Update(responseRoot.Data.Id, model);
            }
            else if (response.StatusCode == HttpStatusCode.NoContent)
            {
                ModelRegistry.ApplyPatch(model, patch);
            }

            // create and cache includes
            await Task.WhenAll(allModels.Select(x => Task.Run(() =>
            {
                var resource = ModelRegistry.GetResource(x);
                Cache.Update(resource.Id, x);
            })));
        }
Пример #3
0
        private async Task <HttpContent> BuildHttpContent(ResourceRootSingle root)
        {
            /* The streaming approach appears to have reduced the memory footprint by a decent
             * margin (maybe a third). I suspect that StringContent just copies the string to a
             * MemoryStream anyway so we're only reducing that extra step of string to stream. */
            //return new StringContent(root.ToJson(JsonSettings), Encoding.UTF8, JsonApiHeader);

            var serializer = JsonSerializer.CreateDefault(new JsonSerializerSettings
            {
                NullValueHandling = NullValueHandling.Ignore,
                Formatting        = Formatting.None
            });

            var stream = new MemoryStream();
            var sr     = new StreamWriter(stream);
            var writer = new JsonTextWriter(sr);

            serializer.Serialize(writer, root);
            await writer.FlushAsync();

            stream.Seek(0, SeekOrigin.Begin);
            var content = new StreamContent(stream);

            content.Headers.ContentType = new MediaTypeHeaderValue(JsonApiHeader)
            {
                CharSet = Encoding.UTF8.WebName
            };
            return(content);
        }
Пример #4
0
        public async Task <HttpRequestMessage> CreateResource(ResourceRootSingle root)
        {
            var request = new HttpRequestMessage(HttpMethod.Post, root.Data.Type);

            HttpRequestModifier?.CreateResource(request, root);
            // Allowing the RequestModifier to set custom content, if they really wanted to
            if (request.Content == null)
            {
                request.Content = await BuildHttpContent(root);
            }
            return(request);
        }
Пример #5
0
        public async Task <HttpRequestMessage> UpdateResource(Resource resource, ResourceRootSingle root)
        {
            var request = new HttpRequestMessage(new HttpMethod("PATCH"), $"{root.Data.Type}/{root.Data.Id}");

            HttpRequestModifier?.UpdateResource(request, resource, root);
            // Allowing the RequestModifier to set custom content, if they really wanted to
            if (request.Content == null)
            {
                request.Content = await BuildHttpContent(root);
            }
            return(request);
        }
Пример #6
0
        public async Task Get__Given_ModelId__When_DataRetrieved__Then_CreateAndCacheModel
            (Guid modelId)
        {
            var uri             = "http://www.test.com/";
            var expectedRequest = new HttpRequestMessage(HttpMethod.Get, new Uri(uri));

            var modelRegistry = CreateModelRegistry(typeof(BasicModel));

            var resourceType = modelRegistry.GetResourceType <BasicModel>();

            var mockRequestBuilder = new Mock <IHttpRequestBuilder>();

            mockRequestBuilder
            .Setup(x => x.GetResource(modelId, resourceType, string.Empty))
            .Returns(expectedRequest);

            var mockHandler = new MockRequestHandler();

            mockHandler.Setup(
                new Uri(uri),
                request =>
            {
                Assert.Same(expectedRequest, request);
                var root =
                    ResourceRootSingle.FromResource(
                        new Resource {
                    Id = modelId, Type = modelRegistry.GetResourceType <BasicModel>()
                });
                return(Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK)
                {
                    Content = new StringContent(JsonConvert.SerializeObject(root))
                }));
            });

            var mockCacheProvider = new Mock <ICacheProvider>();

            var subject = CreateSubject(
                mockHandler,
                mockRequestBuilder.Object,
                mockCacheProvider.Object,
                modelRegistry);

            var result = await subject.Get <BasicModel>(modelId);

            Assert.NotNull(result);
            Assert.Equal(modelId, result.Id);

            mockCacheProvider.Verify(x => x.Update(modelId, result), Times.Once);
        }
Пример #7
0
 public override void UpdateResource(HttpRequestMessage request, Resource originalResource, ResourceRootSingle patch)
 {
     foreach (var httpRequestModifier in HttpRequestModifiers)
     {
         httpRequestModifier.UpdateResource(request, originalResource, patch);
     }
 }
Пример #8
0
 /// <summary>
 /// Called by requests to update a resource
 /// </summary>
 /// <param name="statusCode">Response status</param>
 /// <param name="originalResource">Resource being updated</param>
 /// <param name="patch">Resource patch</param>
 public virtual Task UpdateResource(HttpStatusCode statusCode, Resource originalResource, ResourceRootSingle patch)
 {
     // Do nothing
     return(Task.CompletedTask);
 }
Пример #9
0
 /// <summary>
 /// Called by requests to create a resource
 /// </summary>
 /// <param name="statusCode">Whether Argo considers the response code successful.</param>
 /// <param name="resource">Resource being created</param>
 public virtual Task CreateResource(HttpStatusCode statusCode, ResourceRootSingle resource)
 {
     // Do nothing
     return(Task.CompletedTask);
 }
Пример #10
0
        private async Task <TModel> Create <TModel>(Type rootModelType, object model)
        {
            ThrowIfDisposed();

            // set Id if unset
            var modelId = model == null
                ? Guid.NewGuid()
                : ModelRegistry.GetOrCreateId(model);

            if (modelId == Guid.Empty)
            {
                modelId = Guid.NewGuid();
                ModelRegistry.SetId(model, modelId);
            }

            // Create a new model instance if not already existing
            if (model == null)
            {
                model = Activator.CreateInstance <TModel>();
                ModelRegistry.SetId(model, modelId);
            }

            if (ModelRegistry.IsManagedModel(model))
            {
                throw new ManagedModelCreationException(model.GetType(), modelId);
            }

            // all unmanaged models in the object graph, including root
            var allModels = ModelRegistry.IncludedModelsCreate(model);

            foreach (var newModel in allModels)
            {
                var newResource = BuildModelResource(newModel);
                // Update the model instance in the argument
                var initialize = newModel.GetType().GetInitializeMethod();
                initialize.Invoke(newModel, new object[] { newResource, this });
            }

            var rootResource = ModelRegistry.GetResource(model);
            var includes     = allModels.Where(x => x != model).Select(ModelRegistry.GetResource).ToArray();

            if (Log.IsDebugEnabled())
            {
                Log.Debug(() => $"preparing to POST {rootResource.Type}:{{{rootResource.Id}}}");
                foreach (var include in includes)
                {
                    Log.Debug(() => $"preparing to POST included {include.Type}:{{{include.Id}}}");
                }
            }


            var root    = ResourceRootSingle.FromResource(rootResource, includes);
            var request = await HttpRequestBuilder.CreateResource(root);

            var response = await HttpClient.SendAsync(request).ConfigureAwait(false);

            HttpResponseListener.CreateResource(response.StatusCode, root);
            response.CheckStatusCode();
            if (response.StatusCode == HttpStatusCode.Created)
            {
                var responseRoot = await response.GetContentModel <ResourceRootSingle>(JsonSettings);

                // Update the model instance in the argument
                var initialize = rootModelType.GetInitializeMethod();
                initialize.Invoke(model, new object[] { responseRoot.Data, this });
            }

            // create and cache includes
            await Task.WhenAll(allModels.Select(x => Task.Run(() =>
            {
                var resource = ModelRegistry.GetResource(x);
                Cache.Update(resource.Id, x);
            })));

            return((TModel)model);
        }
Пример #11
0
 /// <summary>
 /// Modifies requests to update a resource
 /// </summary>
 /// <param name="request"></param>
 /// <param name="originalResource">Resource being updated</param>
 /// <param name="patch">Resource patch</param>
 public virtual void UpdateResource(HttpRequestMessage request, Resource originalResource, ResourceRootSingle patch)
 {
     // Do nothing
 }
Пример #12
0
 public override Task UpdateResource(HttpStatusCode statusCode, Resource originalResource, ResourceRootSingle patch)
 {
     Logger.Information("Patched {Id}. Status: {StatusCode}", patch.Data.Id, statusCode);
     return(Task.CompletedTask);
 }
Пример #13
0
 public override Task CreateResource(HttpStatusCode statusCode, ResourceRootSingle resource)
 {
     Logger.Information("Created {Type}. Status: {StatusCode}", resource.Data.Type, statusCode);
     return(Task.CompletedTask);
 }
Пример #14
0
 public void CreateResource(HttpStatusCode statusCode, ResourceRootSingle resource)
 {
     FireAndForget(HttpResponseListeners
                   .Select(x => x.CreateResource(statusCode, resource)));
 }
Пример #15
0
        public override void UpdateResource(HttpRequestMessage request, Resource originalResource, ResourceRootSingle patch)
        {
            // First check patch then check the original resource
            var eTag = patch.Data.GetMeta().SelectToken(EtagMetaPath)
                       ?? originalResource.GetMeta().SelectToken(EtagMetaPath);

            if (eTag != null)
            {
                request.Headers.IfMatch.Add(GetEtagHeader(eTag.ToString()));
            }
        }
Пример #16
0
 public void UpdateResource(HttpStatusCode statusCode, Resource originalResource, ResourceRootSingle patch)
 {
     FireAndForget(HttpResponseListeners
                   .Select(x => x.UpdateResource(statusCode, originalResource, patch)));
 }
Пример #17
0
 /// <summary>
 /// Modifies requests to create a resource
 /// </summary>
 /// <param name="request"></param>
 /// <param name="resource">Resource being created</param>
 public virtual void CreateResource(HttpRequestMessage request, ResourceRootSingle resource)
 {
     // Do nothing
 }