Skip to content

Commit 80fe2b2

Browse files
author
Bart Koelman
committed
Created custom exception for remaining errors
1 parent ff763f1 commit 80fe2b2

File tree

6 files changed

+98
-28
lines changed

6 files changed

+98
-28
lines changed

src/JsonApiDotNetCore/AtomicOperations/LocalIdTracker.cs

Lines changed: 4 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3-
using System.Net;
43
using JsonApiDotNetCore.Errors;
5-
using JsonApiDotNetCore.Serialization.Objects;
64

75
namespace JsonApiDotNetCore.AtomicOperations
86
{
@@ -32,11 +30,7 @@ private void AssertIsNotDeclared(string localId)
3230
{
3331
if (_idsTracked.ContainsKey(localId))
3432
{
35-
throw new JsonApiException(new ErrorObject(HttpStatusCode.BadRequest)
36-
{
37-
Title = "Another local ID with the same name is already defined at this point.",
38-
Detail = $"Another local ID with name '{localId}' is already defined at this point."
39-
});
33+
throw new DuplicateLocalIdValueException(localId);
4034
}
4135
}
4236

@@ -75,11 +69,7 @@ public string GetValue(string localId, string resourceType)
7569

7670
if (item.ServerId == null)
7771
{
78-
throw new JsonApiException(new ErrorObject(HttpStatusCode.BadRequest)
79-
{
80-
Title = "Local ID cannot be both defined and used within the same operation.",
81-
Detail = $"Local ID '{localId}' cannot be both defined and used within the same operation."
82-
});
72+
throw new LocalIdSingleOperationException(localId);
8373
}
8474

8575
return item.ServerId;
@@ -89,23 +79,15 @@ private void AssertIsDeclared(string localId)
8979
{
9080
if (!_idsTracked.ContainsKey(localId))
9181
{
92-
throw new JsonApiException(new ErrorObject(HttpStatusCode.BadRequest)
93-
{
94-
Title = "Server-generated value for local ID is not available at this point.",
95-
Detail = $"Server-generated value for local ID '{localId}' is not available at this point."
96-
});
82+
throw new UnknownLocalIdValueException(localId);
9783
}
9884
}
9985

10086
private static void AssertSameResourceType(string currentType, string declaredType, string localId)
10187
{
10288
if (declaredType != currentType)
10389
{
104-
throw new JsonApiException(new ErrorObject(HttpStatusCode.BadRequest)
105-
{
106-
Title = "Type mismatch in local ID usage.",
107-
Detail = $"Local ID '{localId}' belongs to resource type '{declaredType}' instead of '{currentType}'."
108-
});
90+
throw new IncompatibleLocalIdTypeException(localId, declaredType, currentType);
10991
}
11092
}
11193

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
using System.Net;
2+
using JetBrains.Annotations;
3+
using JsonApiDotNetCore.Serialization.Objects;
4+
5+
namespace JsonApiDotNetCore.Errors
6+
{
7+
/// <summary>
8+
/// The error that is thrown when assigning a local ID that was already assigned in an earlier operation.
9+
/// </summary>
10+
[PublicAPI]
11+
public sealed class DuplicateLocalIdValueException : JsonApiException
12+
{
13+
public DuplicateLocalIdValueException(string localId)
14+
: base(new ErrorObject(HttpStatusCode.BadRequest)
15+
{
16+
Title = "Another local ID with the same name is already defined at this point.",
17+
Detail = $"Another local ID with name '{localId}' is already defined at this point."
18+
})
19+
{
20+
}
21+
}
22+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
using System.Net;
2+
using JetBrains.Annotations;
3+
using JsonApiDotNetCore.Serialization.Objects;
4+
5+
namespace JsonApiDotNetCore.Errors
6+
{
7+
/// <summary>
8+
/// The error that is thrown when referencing a local ID that was assigned to a different resource type.
9+
/// </summary>
10+
[PublicAPI]
11+
public sealed class IncompatibleLocalIdTypeException : JsonApiException
12+
{
13+
public IncompatibleLocalIdTypeException(string localId, string declaredType, string currentType)
14+
: base(new ErrorObject(HttpStatusCode.BadRequest)
15+
{
16+
Title = "Incompatible type in Local ID usage.",
17+
Detail = $"Local ID '{localId}' belongs to resource type '{declaredType}' instead of '{currentType}'."
18+
})
19+
{
20+
}
21+
}
22+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
using System.Net;
2+
using JetBrains.Annotations;
3+
using JsonApiDotNetCore.Serialization.Objects;
4+
5+
namespace JsonApiDotNetCore.Errors
6+
{
7+
/// <summary>
8+
/// The error that is thrown when assigning and referencing a local ID within the same operation.
9+
/// </summary>
10+
[PublicAPI]
11+
public sealed class LocalIdSingleOperationException : JsonApiException
12+
{
13+
public LocalIdSingleOperationException(string localId)
14+
: base(new ErrorObject(HttpStatusCode.BadRequest)
15+
{
16+
Title = "Local ID cannot be both defined and used within the same operation.",
17+
Detail = $"Local ID '{localId}' cannot be both defined and used within the same operation."
18+
})
19+
{
20+
}
21+
}
22+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
using System.Net;
2+
using JetBrains.Annotations;
3+
using JsonApiDotNetCore.Serialization.Objects;
4+
5+
namespace JsonApiDotNetCore.Errors
6+
{
7+
/// <summary>
8+
/// The error that is thrown when referencing a local ID that hasn't been assigned.
9+
/// </summary>
10+
[PublicAPI]
11+
public sealed class UnknownLocalIdValueException : JsonApiException
12+
{
13+
public UnknownLocalIdValueException(string localId)
14+
: base(new ErrorObject(HttpStatusCode.BadRequest)
15+
{
16+
Title = "Server-generated value for local ID is not available at this point.",
17+
Detail = $"Server-generated value for local ID '{localId}' is not available at this point."
18+
})
19+
{
20+
}
21+
}
22+
}

test/JsonApiDotNetCoreTests/IntegrationTests/AtomicOperations/LocalIds/AtomicLocalIdTests.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2098,7 +2098,7 @@ public async Task Cannot_consume_local_ID_of_different_type_in_same_operation()
20982098

20992099
ErrorObject error = responseDocument.Errors[0];
21002100
error.StatusCode.Should().Be(HttpStatusCode.BadRequest);
2101-
error.Title.Should().Be("Type mismatch in local ID usage.");
2101+
error.Title.Should().Be("Incompatible type in Local ID usage.");
21022102
error.Detail.Should().Be("Local ID 'track-1' belongs to resource type 'musicTracks' instead of 'recordCompanies'.");
21032103
error.Source.Pointer.Should().Be("/atomic:operations[1]");
21042104
}
@@ -2155,7 +2155,7 @@ public async Task Cannot_consume_local_ID_of_different_type_in_ref()
21552155

21562156
ErrorObject error = responseDocument.Errors[0];
21572157
error.StatusCode.Should().Be(HttpStatusCode.BadRequest);
2158-
error.Title.Should().Be("Type mismatch in local ID usage.");
2158+
error.Title.Should().Be("Incompatible type in Local ID usage.");
21592159
error.Detail.Should().Be("Local ID 'company-1' belongs to resource type 'recordCompanies' instead of 'musicTracks'.");
21602160
error.Source.Pointer.Should().Be("/atomic:operations[2]");
21612161
}
@@ -2215,7 +2215,7 @@ public async Task Cannot_consume_local_ID_of_different_type_in_data_element()
22152215

22162216
ErrorObject error = responseDocument.Errors[0];
22172217
error.StatusCode.Should().Be(HttpStatusCode.BadRequest);
2218-
error.Title.Should().Be("Type mismatch in local ID usage.");
2218+
error.Title.Should().Be("Incompatible type in Local ID usage.");
22192219
error.Detail.Should().Be("Local ID 'performer-1' belongs to resource type 'performers' instead of 'playlists'.");
22202220
error.Source.Pointer.Should().Be("/atomic:operations[2]");
22212221
}
@@ -2289,7 +2289,7 @@ await _testContext.RunOnDatabaseAsync(async dbContext =>
22892289

22902290
ErrorObject error = responseDocument.Errors[0];
22912291
error.StatusCode.Should().Be(HttpStatusCode.BadRequest);
2292-
error.Title.Should().Be("Type mismatch in local ID usage.");
2292+
error.Title.Should().Be("Incompatible type in Local ID usage.");
22932293
error.Detail.Should().Be("Local ID 'company-1' belongs to resource type 'recordCompanies' instead of 'performers'.");
22942294
error.Source.Pointer.Should().Be("/atomic:operations[2]");
22952295
}
@@ -2362,7 +2362,7 @@ public async Task Cannot_consume_local_ID_of_different_type_in_relationship_data
23622362

23632363
ErrorObject error = responseDocument.Errors[0];
23642364
error.StatusCode.Should().Be(HttpStatusCode.BadRequest);
2365-
error.Title.Should().Be("Type mismatch in local ID usage.");
2365+
error.Title.Should().Be("Incompatible type in Local ID usage.");
23662366
error.Detail.Should().Be("Local ID 'playlist-1' belongs to resource type 'playlists' instead of 'recordCompanies'.");
23672367
error.Source.Pointer.Should().Be("/atomic:operations[2]");
23682368
}
@@ -2432,7 +2432,7 @@ public async Task Cannot_consume_local_ID_of_different_type_in_relationship_data
24322432

24332433
ErrorObject error = responseDocument.Errors[0];
24342434
error.StatusCode.Should().Be(HttpStatusCode.BadRequest);
2435-
error.Title.Should().Be("Type mismatch in local ID usage.");
2435+
error.Title.Should().Be("Incompatible type in Local ID usage.");
24362436
error.Detail.Should().Be("Local ID 'performer-1' belongs to resource type 'performers' instead of 'musicTracks'.");
24372437
error.Source.Pointer.Should().Be("/atomic:operations[2]");
24382438
}

0 commit comments

Comments
 (0)