Skip to content

Commit 52b1dba

Browse files
authored
Merge pull request #308 from nwise/master
Fixing issue where total-records was 0 on POST and PATCH calls.
2 parents 2a11245 + e6fb926 commit 52b1dba

File tree

5 files changed

+136
-24
lines changed

5 files changed

+136
-24
lines changed

src/JsonApiDotNetCore/Builders/DocumentBuilder.cs

+7-8
Original file line numberDiff line numberDiff line change
@@ -68,21 +68,20 @@ public Documents Build(IEnumerable<IIdentifiable> entities)
6868

6969
private Dictionary<string, object> GetMeta(IIdentifiable entity)
7070
{
71-
if (entity == null) return null;
72-
7371
var builder = _jsonApiContext.MetaBuilder;
74-
75-
if (entity is IHasMeta metaEntity)
76-
builder.Add(metaEntity.GetMeta(_jsonApiContext));
77-
78-
if (_jsonApiContext.Options.IncludeTotalRecordCount)
72+
if (_jsonApiContext.Options.IncludeTotalRecordCount && _jsonApiContext.PageManager.TotalRecords != null)
7973
builder.Add("total-records", _jsonApiContext.PageManager.TotalRecords);
8074

8175
if (_requestMeta != null)
8276
builder.Add(_requestMeta.GetMeta());
8377

78+
if (entity != null && entity is IHasMeta metaEntity)
79+
builder.Add(metaEntity.GetMeta(_jsonApiContext));
80+
8481
var meta = builder.Build();
85-
if (meta.Count > 0) return meta;
82+
if (meta.Count > 0)
83+
return meta;
84+
8685
return null;
8786
}
8887

src/JsonApiDotNetCore/Internal/PageManager.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@ namespace JsonApiDotNetCore.Internal
66
{
77
public class PageManager
88
{
9-
public int TotalRecords { get; set; }
9+
public int? TotalRecords { get; set; }
1010
public int PageSize { get; set; }
1111
public int DefaultPageSize { get; set; }
1212
public int CurrentPage { get; set; }
1313
public bool IsPaginated => PageSize > 0;
14-
public int TotalPages => (TotalRecords == 0) ? -1 : (int)Math.Ceiling(decimal.Divide(TotalRecords, PageSize));
14+
public int TotalPages => (TotalRecords == null) ? -1 : (int)Math.Ceiling(decimal.Divide(TotalRecords.Value, PageSize));
1515

1616
public RootLinks GetPageLinks(LinkBuilder linkBuilder)
1717
{

src/JsonApiDotNetCore/Services/JsonApiContext.cs

+5-5
Original file line numberDiff line numberDiff line change
@@ -86,20 +86,20 @@ internal static bool PathIsRelationship(string requestPath)
8686
const char pathSegmentDelimiter = '/';
8787

8888
var span = requestPath.AsSpan();
89-
89+
9090
// we need to iterate over the string, from the end,
9191
// checking whether or not the 2nd to last path segment
9292
// is "relationships"
9393
// -2 is chosen in case the path ends with '/'
94-
for(var i = requestPath.Length - 2; i >= 0; i--)
94+
for (var i = requestPath.Length - 2; i >= 0; i--)
9595
{
9696
// if there are not enough characters left in the path to
9797
// contain "relationships"
98-
if(i < relationships.Length)
98+
if (i < relationships.Length)
9999
return false;
100100

101101
// we have found the first instance of '/'
102-
if(span[i] == pathSegmentDelimiter)
102+
if (span[i] == pathSegmentDelimiter)
103103
{
104104
// in the case of a "relationships" route, the next
105105
// path segment will be "relationships"
@@ -112,7 +112,7 @@ internal static bool PathIsRelationship(string requestPath)
112112

113113
return false;
114114
}
115-
115+
116116
private PageManager GetPageManager()
117117
{
118118
if (Options.DefaultPageSize == 0 && (QuerySet == null || QuerySet.PageQuery.PageSize == 0))

test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/DocumentTests/Meta.cs

+118-7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System.Collections;
22
using System.Net;
33
using System.Net.Http;
4+
using System.Net.Http.Headers;
45
using System.Threading.Tasks;
56
using JsonApiDotNetCore.Models;
67
using JsonApiDotNetCoreExample;
@@ -47,13 +48,123 @@ public async Task Total_Record_Count_Included()
4748
var response = await client.SendAsync(request);
4849
var responseBody = await response.Content.ReadAsStringAsync();
4950
var documents = JsonConvert.DeserializeObject<Documents>(responseBody);
50-
51+
5152
// assert
5253
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
5354
Assert.NotNull(documents.Meta);
5455
Assert.Equal((long)expectedCount, (long)documents.Meta["total-records"]);
5556
}
5657

58+
[Fact]
59+
public async Task Total_Record_Count_Included_When_None()
60+
{
61+
// arrange
62+
_context.TodoItems.RemoveRange(_context.TodoItems);
63+
_context.SaveChanges();
64+
var builder = new WebHostBuilder()
65+
.UseStartup<MetaStartup>();
66+
67+
var httpMethod = new HttpMethod("GET");
68+
var route = $"/api/v1/todo-items";
69+
70+
var server = new TestServer(builder);
71+
var client = server.CreateClient();
72+
var request = new HttpRequestMessage(httpMethod, route);
73+
74+
// act
75+
var response = await client.SendAsync(request);
76+
var responseBody = await response.Content.ReadAsStringAsync();
77+
var documents = JsonConvert.DeserializeObject<Documents>(responseBody);
78+
79+
// assert
80+
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
81+
Assert.NotNull(documents.Meta);
82+
Assert.Equal(0, (long)documents.Meta["total-records"]);
83+
}
84+
85+
[Fact]
86+
public async Task Total_Record_Count_Not_Included_In_POST_Response()
87+
{
88+
// arrange
89+
_context.TodoItems.RemoveRange(_context.TodoItems);
90+
_context.SaveChanges();
91+
var builder = new WebHostBuilder()
92+
.UseStartup<MetaStartup>();
93+
94+
var httpMethod = new HttpMethod("POST");
95+
var route = $"/api/v1/todo-items";
96+
97+
var server = new TestServer(builder);
98+
var client = server.CreateClient();
99+
var request = new HttpRequestMessage(httpMethod, route);
100+
var content = new
101+
{
102+
data = new
103+
{
104+
type = "todo-items",
105+
attributes = new
106+
{
107+
description = "New Description",
108+
}
109+
}
110+
};
111+
112+
request.Content = new StringContent(JsonConvert.SerializeObject(content));
113+
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.api+json");
114+
115+
// act
116+
var response = await client.SendAsync(request);
117+
var responseBody = await response.Content.ReadAsStringAsync();
118+
var documents = JsonConvert.DeserializeObject<Document>(responseBody);
119+
120+
// assert
121+
Assert.Equal(HttpStatusCode.Created, response.StatusCode);
122+
Assert.False(documents.Meta.ContainsKey("total-records"));
123+
}
124+
125+
[Fact]
126+
public async Task Total_Record_Count_Not_Included_In_PATCH_Response()
127+
{
128+
// arrange
129+
_context.TodoItems.RemoveRange(_context.TodoItems);
130+
TodoItem todoItem = new TodoItem();
131+
_context.TodoItems.Add(todoItem);
132+
_context.SaveChanges();
133+
var builder = new WebHostBuilder()
134+
.UseStartup<MetaStartup>();
135+
136+
var httpMethod = new HttpMethod("PATCH");
137+
var route = $"/api/v1/todo-items/{todoItem.Id}";
138+
139+
var server = new TestServer(builder);
140+
var client = server.CreateClient();
141+
var request = new HttpRequestMessage(httpMethod, route);
142+
var content = new
143+
{
144+
data = new
145+
{
146+
type = "todo-items",
147+
id = todoItem.Id,
148+
attributes = new
149+
{
150+
description = "New Description",
151+
}
152+
}
153+
};
154+
155+
request.Content = new StringContent(JsonConvert.SerializeObject(content));
156+
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.api+json");
157+
158+
// act
159+
var response = await client.SendAsync(request);
160+
var responseBody = await response.Content.ReadAsStringAsync();
161+
var documents = JsonConvert.DeserializeObject<Document>(responseBody);
162+
163+
// assert
164+
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
165+
Assert.False(documents.Meta.ContainsKey("total-records"));
166+
}
167+
57168
[Fact]
58169
public async Task EntityThatImplements_IHasMeta_Contains_MetaData()
59170
{
@@ -73,26 +184,26 @@ public async Task EntityThatImplements_IHasMeta_Contains_MetaData()
73184
// act
74185
var response = await client.SendAsync(request);
75186
var documents = JsonConvert.DeserializeObject<Documents>(await response.Content.ReadAsStringAsync());
76-
187+
77188
// assert
78189
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
79190
Assert.NotNull(documents.Meta);
80191
Assert.NotNull(expectedMeta);
81192
Assert.NotEmpty(expectedMeta);
82-
83-
foreach(var hash in expectedMeta)
193+
194+
foreach (var hash in expectedMeta)
84195
{
85-
if(hash.Value is IList)
196+
if (hash.Value is IList)
86197
{
87198
var listValue = (IList)hash.Value;
88-
for(var i=0; i < listValue.Count; i++)
199+
for (var i = 0; i < listValue.Count; i++)
89200
Assert.Equal(listValue[i].ToString(), ((IList)documents.Meta[hash.Key])[i].ToString());
90201
}
91202
else
92203
{
93204
Assert.Equal(hash.Value, documents.Meta[hash.Key]);
94205
}
95-
}
206+
}
96207
}
97208
}
98209
}

test/JsonApiDotNetCoreExampleTests/Acceptance/Spec/FetchingDataTests.cs

+4-2
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,10 @@ public async Task Request_ForEmptyCollection_Returns_EmptyDataCollection()
5353
var server = new TestServer(builder);
5454
var client = server.CreateClient();
5555
var request = new HttpRequestMessage(httpMethod, route);
56-
var expectedBody = JsonConvert.SerializeObject(new {
57-
data = new List<object>()
56+
var expectedBody = JsonConvert.SerializeObject(new
57+
{
58+
data = new List<object>(),
59+
meta = new Dictionary<string, int> { { "total-records", 0 } }
5860
});
5961

6062
// act

0 commit comments

Comments
 (0)