From 5e615e890c298105e857abb5bd419c0a8be4e4fb Mon Sep 17 00:00:00 2001 From: Milos Date: Sun, 9 Dec 2018 22:22:10 +0100 Subject: [PATCH 1/2] Allow filter[id] and filter[related.id] --- .../Builders/ContextGraphBuilder.cs | 11 +++++ .../Builders/DocumentBuilder.cs | 8 +++- .../Acceptance/TodoItemsControllerTests.cs | 48 +++++++++++++++++++ .../Builders/ContextGraphBuilder_Tests.cs | 4 +- 4 files changed, 67 insertions(+), 4 deletions(-) diff --git a/src/JsonApiDotNetCore/Builders/ContextGraphBuilder.cs b/src/JsonApiDotNetCore/Builders/ContextGraphBuilder.cs index ca6caad1f8..da540b85a3 100644 --- a/src/JsonApiDotNetCore/Builders/ContextGraphBuilder.cs +++ b/src/JsonApiDotNetCore/Builders/ContextGraphBuilder.cs @@ -139,6 +139,17 @@ protected virtual List GetAttributes(Type entityType) foreach (var prop in properties) { + if (prop.Name == nameof(Identifiable.Id)) + { + var idAttr = new AttrAttribute() + { + PublicAttributeName = JsonApiOptions.ResourceNameFormatter.FormatPropertyName(prop), + PropertyInfo = prop, + InternalAttributeName = prop.Name + }; + attributes.Add(idAttr); + } + var attribute = (AttrAttribute)prop.GetCustomAttribute(typeof(AttrAttribute)); if (attribute == null) continue; diff --git a/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs b/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs index 82c3d2ec75..5261140e5d 100644 --- a/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs +++ b/src/JsonApiDotNetCore/Builders/DocumentBuilder.cs @@ -141,6 +141,7 @@ public ResourceObject GetData(ContextEntity contextEntity, IIdentifiable entity, private bool ShouldIncludeAttribute(AttrAttribute attr, object attributeValue) { return OmitNullValuedAttribute(attr, attributeValue) == false + && attr.InternalAttributeName != nameof(Identifiable.Id) && ((_jsonApiContext.QuerySet == null || _jsonApiContext.QuerySet.Fields.Count == 0) || _jsonApiContext.QuerySet.Fields.Contains(attr.InternalAttributeName)); @@ -280,10 +281,13 @@ private ResourceObject GetIncludedEntity(IIdentifiable entity) data.Attributes = new Dictionary(); - contextEntity.Attributes.ForEach(attr => + foreach(var attr in contextEntity.Attributes) { + if (attr.InternalAttributeName == nameof(Identifiable.Id)) + continue; + data.Attributes.Add(attr.PublicAttributeName, attr.GetValue(entity)); - }); + } return data; } diff --git a/test/JsonApiDotNetCoreExampleTests/Acceptance/TodoItemsControllerTests.cs b/test/JsonApiDotNetCoreExampleTests/Acceptance/TodoItemsControllerTests.cs index 618db7dd10..69bcccb2a2 100644 --- a/test/JsonApiDotNetCoreExampleTests/Acceptance/TodoItemsControllerTests.cs +++ b/test/JsonApiDotNetCoreExampleTests/Acceptance/TodoItemsControllerTests.cs @@ -69,6 +69,54 @@ public async Task Can_Get_TodoItems() Assert.True(deserializedBody.Count <= expectedEntitiesPerPage); } + [Fact] + public async Task Can_Filter_By_Resource_Id() + { + // Arrange + var todoItem = _todoItemFaker.Generate(); + _context.TodoItems.Add(todoItem); + _context.SaveChanges(); + + var httpMethod = new HttpMethod("GET"); + var route = $"/api/v1/todo-items?filter[id]={todoItem.Id}"; + var request = new HttpRequestMessage(httpMethod, route); + + // Act + var response = await _fixture.Client.SendAsync(request); + var body = await response.Content.ReadAsStringAsync(); + var deserializedBody = _fixture.GetService().DeserializeList(body); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.NotEmpty(deserializedBody); + Assert.Contains(deserializedBody, (i) => i.Id == todoItem.Id); + } + + [Fact] + public async Task Can_Filter_By_Relationship_Id() + { + // Arrange + var person = new Person(); + var todoItem = _todoItemFaker.Generate(); + todoItem.Owner = person; + _context.TodoItems.Add(todoItem); + _context.SaveChanges(); + + var httpMethod = new HttpMethod("GET"); + var route = $"/api/v1/todo-items?filter[owner.id]={person.Id}"; + var request = new HttpRequestMessage(httpMethod, route); + + // Act + var response = await _fixture.Client.SendAsync(request); + var body = await response.Content.ReadAsStringAsync(); + var deserializedBody = _fixture.GetService().DeserializeList(body); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.NotEmpty(deserializedBody); + Assert.Contains(deserializedBody, (i) => i.OwnerId == person.Id); + } + [Fact] public async Task Can_Filter_TodoItems() { diff --git a/test/UnitTests/Builders/ContextGraphBuilder_Tests.cs b/test/UnitTests/Builders/ContextGraphBuilder_Tests.cs index eab003309f..a88ecceb67 100644 --- a/test/UnitTests/Builders/ContextGraphBuilder_Tests.cs +++ b/test/UnitTests/Builders/ContextGraphBuilder_Tests.cs @@ -94,7 +94,7 @@ public void Attrs_Without_Names_Specified_Will_Use_Default_Formatter() // assert var resource = graph.GetContextEntity(typeof(TestResource)); - Assert.Equal("compound-attribute", resource.Attributes.Single().PublicAttributeName); + Assert.Contains(resource.Attributes, (i) => i.PublicAttributeName == "compound-attribute"); } [Fact] @@ -110,7 +110,7 @@ public void Attrs_Without_Names_Specified_Will_Use_Configured_Formatter() // assert var resource = graph.GetContextEntity(typeof(TestResource)); - Assert.Equal("compoundAttribute", resource.Attributes.Single().PublicAttributeName); + Assert.Contains(resource.Attributes, (i) => i.PublicAttributeName == "compoundAttribute"); } [Fact] From 7268b661cbfbc193031ed82e1174d3da91f0274c Mon Sep 17 00:00:00 2001 From: Milos Date: Mon, 10 Dec 2018 07:53:12 +0100 Subject: [PATCH 2/2] Add continue --- src/JsonApiDotNetCore/Builders/ContextGraphBuilder.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/JsonApiDotNetCore/Builders/ContextGraphBuilder.cs b/src/JsonApiDotNetCore/Builders/ContextGraphBuilder.cs index da540b85a3..923ca074e5 100644 --- a/src/JsonApiDotNetCore/Builders/ContextGraphBuilder.cs +++ b/src/JsonApiDotNetCore/Builders/ContextGraphBuilder.cs @@ -148,6 +148,7 @@ protected virtual List GetAttributes(Type entityType) InternalAttributeName = prop.Name }; attributes.Add(idAttr); + continue; } var attribute = (AttrAttribute)prop.GetCustomAttribute(typeof(AttrAttribute));