Skip to content

Commit d5d5c8d

Browse files
author
Bart Koelman
committed
Unified error messages about the absense of 'type'
1 parent c9a4f5a commit d5d5c8d

22 files changed

+61
-65
lines changed

src/JsonApiDotNetCore/Serialization/RequestAdapters/ResourceIdentityAdapter.cs

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -109,19 +109,7 @@ protected ResourceIdentityAdapter(IResourceGraph resourceGraph, IResourceFactory
109109

110110
private ResourceContext ConvertType(IResourceIdentity identity, ResourceIdentityRequirements requirements, RequestAdapterState state)
111111
{
112-
if (identity.Type == null)
113-
{
114-
string parent = identity is AtomicReference
115-
? "'ref' element"
116-
:
117-
requirements?.RelationshipName != null &&
118-
state.Request.WriteOperation is WriteOperationKind.CreateResource or WriteOperationKind.UpdateResource
119-
?
120-
$"'{requirements.RelationshipName}' relationship"
121-
: "'data' element";
122-
123-
throw new DeserializationException(state.Position, "Request body must include 'type' element.", $"Expected 'type' element in {parent}.");
124-
}
112+
AssertHasType(identity, state);
125113

126114
using IDisposable _ = state.Position.PushElement("type");
127115

@@ -165,6 +153,14 @@ state.Request.WriteOperation is WriteOperationKind.CreateResource or WriteOperat
165153
return resourceContext;
166154
}
167155

156+
private static void AssertHasType(IResourceIdentity identity, RequestAdapterState state)
157+
{
158+
if (identity.Type == null)
159+
{
160+
throw new ModelConversionException(state.Position, "The 'type' element is required.", null);
161+
}
162+
}
163+
168164
private static void AssertIsKnownResourceType(ResourceContext resourceContext, string typeName, RequestAdapterState state)
169165
{
170166
if (resourceContext == null)

test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -598,8 +598,8 @@ public async Task Cannot_create_resource_for_missing_type()
598598

599599
ErrorObject error = responseDocument.Errors[0];
600600
error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity);
601-
error.Title.Should().Be("Failed to deserialize request body: Request body must include 'type' element.");
602-
error.Detail.Should().Be("Expected 'type' element in 'data' element.");
601+
error.Title.Should().Be("Failed to deserialize request body: The 'type' element is required.");
602+
error.Detail.Should().BeNull();
603603
error.Source.Pointer.Should().Be("/atomic:operations[0]/data");
604604
}
605605

test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceWithToManyRelationshipTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -232,8 +232,8 @@ public async Task Cannot_create_for_missing_relationship_type()
232232

233233
ErrorObject error = responseDocument.Errors[0];
234234
error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity);
235-
error.Title.Should().Be("Failed to deserialize request body: Request body must include 'type' element.");
236-
error.Detail.Should().Be("Expected 'type' element in 'performers' relationship.");
235+
error.Title.Should().Be("Failed to deserialize request body: The 'type' element is required.");
236+
error.Detail.Should().BeNull();
237237
error.Source.Pointer.Should().Be("/atomic:operations[0]/data/relationships/performers/data[0]");
238238
}
239239

test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Creating/AtomicCreateResourceWithToOneRelationshipTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -297,8 +297,8 @@ public async Task Cannot_create_for_missing_relationship_type()
297297

298298
ErrorObject error = responseDocument.Errors[0];
299299
error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity);
300-
error.Title.Should().Be("Failed to deserialize request body: Request body must include 'type' element.");
301-
error.Detail.Should().Be("Expected 'type' element in 'lyric' relationship.");
300+
error.Title.Should().Be("Failed to deserialize request body: The 'type' element is required.");
301+
error.Detail.Should().BeNull();
302302
error.Source.Pointer.Should().Be("/atomic:operations[0]/data/relationships/lyric/data");
303303
}
304304

test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Deleting/AtomicDeleteResourceTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -424,8 +424,8 @@ public async Task Cannot_delete_resource_for_missing_type()
424424

425425
ErrorObject error = responseDocument.Errors[0];
426426
error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity);
427-
error.Title.Should().Be("Failed to deserialize request body: Request body must include 'type' element.");
428-
error.Detail.Should().Be("Expected 'type' element in 'ref' element.");
427+
error.Title.Should().Be("Failed to deserialize request body: The 'type' element is required.");
428+
error.Detail.Should().BeNull();
429429
error.Source.Pointer.Should().Be("/atomic:operations[0]/ref");
430430
}
431431

test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicAddToToManyRelationshipTests.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -300,8 +300,8 @@ public async Task Cannot_add_for_missing_type_in_ref()
300300

301301
ErrorObject error = responseDocument.Errors[0];
302302
error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity);
303-
error.Title.Should().Be("Failed to deserialize request body: Request body must include 'type' element.");
304-
error.Detail.Should().Be("Expected 'type' element in 'ref' element.");
303+
error.Title.Should().Be("Failed to deserialize request body: The 'type' element is required.");
304+
error.Detail.Should().BeNull();
305305
error.Source.Pointer.Should().Be("/atomic:operations[0]/ref");
306306
}
307307

@@ -637,8 +637,8 @@ public async Task Cannot_add_for_missing_type_in_data()
637637

638638
ErrorObject error = responseDocument.Errors[0];
639639
error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity);
640-
error.Title.Should().Be("Failed to deserialize request body: Request body must include 'type' element.");
641-
error.Detail.Should().Be("Expected 'type' element in 'data' element.");
640+
error.Title.Should().Be("Failed to deserialize request body: The 'type' element is required.");
641+
error.Detail.Should().BeNull();
642642
error.Source.Pointer.Should().Be("/atomic:operations[0]/data[0]");
643643
}
644644

test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicRemoveFromToManyRelationshipTests.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -300,8 +300,8 @@ public async Task Cannot_remove_for_missing_type_in_ref()
300300

301301
ErrorObject error = responseDocument.Errors[0];
302302
error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity);
303-
error.Title.Should().Be("Failed to deserialize request body: Request body must include 'type' element.");
304-
error.Detail.Should().Be("Expected 'type' element in 'ref' element.");
303+
error.Title.Should().Be("Failed to deserialize request body: The 'type' element is required.");
304+
error.Detail.Should().BeNull();
305305
error.Source.Pointer.Should().Be("/atomic:operations[0]/ref");
306306
}
307307

@@ -600,8 +600,8 @@ public async Task Cannot_remove_for_missing_type_in_data()
600600

601601
ErrorObject error = responseDocument.Errors[0];
602602
error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity);
603-
error.Title.Should().Be("Failed to deserialize request body: Request body must include 'type' element.");
604-
error.Detail.Should().Be("Expected 'type' element in 'data' element.");
603+
error.Title.Should().Be("Failed to deserialize request body: The 'type' element is required.");
604+
error.Detail.Should().BeNull();
605605
error.Source.Pointer.Should().Be("/atomic:operations[0]/data[0]");
606606
}
607607

test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicReplaceToManyRelationshipTests.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -336,8 +336,8 @@ public async Task Cannot_replace_for_missing_type_in_ref()
336336

337337
ErrorObject error = responseDocument.Errors[0];
338338
error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity);
339-
error.Title.Should().Be("Failed to deserialize request body: Request body must include 'type' element.");
340-
error.Detail.Should().Be("Expected 'type' element in 'ref' element.");
339+
error.Title.Should().Be("Failed to deserialize request body: The 'type' element is required.");
340+
error.Detail.Should().BeNull();
341341
error.Source.Pointer.Should().Be("/atomic:operations[0]/ref");
342342
}
343343

@@ -692,8 +692,8 @@ public async Task Cannot_replace_for_missing_type_in_data()
692692

693693
ErrorObject error = responseDocument.Errors[0];
694694
error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity);
695-
error.Title.Should().Be("Failed to deserialize request body: Request body must include 'type' element.");
696-
error.Detail.Should().Be("Expected 'type' element in 'data' element.");
695+
error.Title.Should().Be("Failed to deserialize request body: The 'type' element is required.");
696+
error.Detail.Should().BeNull();
697697
error.Source.Pointer.Should().Be("/atomic:operations[0]/data[0]");
698698
}
699699

test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Relationships/AtomicUpdateToOneRelationshipTests.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -583,8 +583,8 @@ public async Task Cannot_create_for_missing_type_in_ref()
583583

584584
ErrorObject error = responseDocument.Errors[0];
585585
error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity);
586-
error.Title.Should().Be("Failed to deserialize request body: Request body must include 'type' element.");
587-
error.Detail.Should().Be("Expected 'type' element in 'ref' element.");
586+
error.Title.Should().Be("Failed to deserialize request body: The 'type' element is required.");
587+
error.Detail.Should().BeNull();
588588
error.Source.Pointer.Should().Be("/atomic:operations[0]/ref");
589589
}
590590

@@ -935,8 +935,8 @@ public async Task Cannot_create_for_missing_type_in_data()
935935

936936
ErrorObject error = responseDocument.Errors[0];
937937
error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity);
938-
error.Title.Should().Be("Failed to deserialize request body: Request body must include 'type' element.");
939-
error.Detail.Should().Be("Expected 'type' element in 'data' element.");
938+
error.Title.Should().Be("Failed to deserialize request body: The 'type' element is required.");
939+
error.Detail.Should().BeNull();
940940
error.Source.Pointer.Should().Be("/atomic:operations[0]/data");
941941
}
942942

test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/Updating/Resources/AtomicReplaceToManyRelationshipTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -388,8 +388,8 @@ public async Task Cannot_replace_for_missing_type_in_relationship_data()
388388

389389
ErrorObject error = responseDocument.Errors[0];
390390
error.StatusCode.Should().Be(HttpStatusCode.UnprocessableEntity);
391-
error.Title.Should().Be("Failed to deserialize request body: Request body must include 'type' element.");
392-
error.Detail.Should().Be("Expected 'type' element in 'tracks' relationship.");
391+
error.Title.Should().Be("Failed to deserialize request body: The 'type' element is required.");
392+
error.Detail.Should().BeNull();
393393
error.Source.Pointer.Should().Be("/atomic:operations[0]/data/relationships/tracks/data[0]");
394394
}
395395

0 commit comments

Comments
 (0)