1
1
using System ;
2
2
using System . Net ;
3
3
using JsonApiDotNetCore . Configuration ;
4
- using JsonApiDotNetCore . Errors ;
5
4
using JsonApiDotNetCore . Middleware ;
6
5
using JsonApiDotNetCore . Resources ;
7
6
using JsonApiDotNetCore . Resources . Annotations ;
@@ -34,75 +33,7 @@ protected ResourceIdentityAdapter(IResourceGraph resourceGraph, IResourceFactory
34
33
ArgumentGuard . NotNull ( state , nameof ( state ) ) ;
35
34
36
35
ResourceContext resourceContext = ConvertType ( identity , requirements , state ) ;
37
-
38
- if ( state . Request . Kind != EndpointKind . AtomicOperations )
39
- {
40
- AssertHasNoLid ( identity , state ) ;
41
- }
42
-
43
- AssertNoIdWithLid ( identity , state ) ;
44
-
45
- if ( requirements . IdConstraint == JsonElementConstraint . Required )
46
- {
47
- AssertHasIdOrLid ( identity , state ) ;
48
- }
49
- else if ( requirements . IdConstraint == JsonElementConstraint . Forbidden )
50
- {
51
- AssertHasNoId ( identity , state ) ;
52
- }
53
-
54
- if ( requirements . IdValue != null && identity . Id != null && identity . Id != requirements . IdValue )
55
- {
56
- using ( state . Position . PushElement ( "id" ) )
57
- {
58
- if ( state . Request . Kind == EndpointKind . AtomicOperations )
59
- {
60
- throw new DeserializationException ( state . Position , "Resource ID mismatch between 'ref.id' and 'data.id' element." ,
61
- $ "Expected resource with ID '{ requirements . IdValue } ' in 'data.id', instead of '{ identity . Id } '.") ;
62
- }
63
-
64
- throw new JsonApiException ( new ErrorObject ( HttpStatusCode . Conflict )
65
- {
66
- Title = "Resource ID mismatch between request body and endpoint URL." ,
67
- Detail = $ "Expected resource ID '{ requirements . IdValue } ', instead of '{ identity . Id } '.",
68
- Source = new ErrorSource
69
- {
70
- Pointer = state . Position . ToSourcePointer ( )
71
- }
72
- } ) ;
73
- }
74
- }
75
-
76
- if ( requirements . LidValue != null && identity . Lid != null && identity . Lid != requirements . LidValue )
77
- {
78
- using ( state . Position . PushElement ( "lid" ) )
79
- {
80
- throw new DeserializationException ( state . Position , "Resource local ID mismatch between 'ref.lid' and 'data.lid' element." ,
81
- $ "Expected resource with local ID '{ requirements . LidValue } ' in 'data.lid', instead of '{ identity . Lid } '.") ;
82
- }
83
- }
84
-
85
- if ( requirements . IdValue != null && identity . Lid != null )
86
- {
87
- using ( state . Position . PushElement ( "lid" ) )
88
- {
89
- throw new DeserializationException ( state . Position , "Resource identity mismatch between 'ref.id' and 'data.lid' element." ,
90
- $ "Expected resource with ID '{ requirements . IdValue } ' in 'data.id', instead of '{ identity . Lid } ' in 'data.lid'.") ;
91
- }
92
- }
93
-
94
- if ( requirements . LidValue != null && identity . Id != null )
95
- {
96
- using ( state . Position . PushElement ( "id" ) )
97
- {
98
- throw new DeserializationException ( state . Position , "Resource identity mismatch between 'ref.lid' and 'data.id' element." ,
99
- $ "Expected resource with local ID '{ requirements . LidValue } ' in 'data.lid', instead of '{ identity . Id } ' in 'data.id'.") ;
100
- }
101
- }
102
-
103
- IIdentifiable resource = _resourceFactory . CreateInstance ( resourceContext . ResourceType ) ;
104
- AssignStringId ( identity , resource , state ) ;
105
- resource . LocalId = identity . Lid ;
36
+ IIdentifiable resource = CreateResource ( identity , requirements , resourceContext . ResourceType , state ) ;
106
37
107
38
return ( resource , resourceContext ) ;
108
39
}
@@ -148,6 +79,34 @@ private static void AssertIsCompatibleResourceType(ResourceContext actual, Resou
148
79
}
149
80
}
150
81
82
+ private IIdentifiable CreateResource ( IResourceIdentity identity , ResourceIdentityRequirements requirements , Type resourceType ,
83
+ RequestAdapterState state )
84
+ {
85
+ if ( state . Request . Kind != EndpointKind . AtomicOperations )
86
+ {
87
+ AssertHasNoLid ( identity , state ) ;
88
+ }
89
+
90
+ AssertNoIdWithLid ( identity , state ) ;
91
+
92
+ if ( requirements . IdConstraint == JsonElementConstraint . Required )
93
+ {
94
+ AssertHasIdOrLid ( identity , requirements , state ) ;
95
+ }
96
+ else if ( requirements . IdConstraint == JsonElementConstraint . Forbidden )
97
+ {
98
+ AssertHasNoId ( identity , state ) ;
99
+ }
100
+
101
+ AssertSameIdValue ( identity , requirements . IdValue , state ) ;
102
+ AssertSameLidValue ( identity , requirements . LidValue , state ) ;
103
+
104
+ IIdentifiable resource = _resourceFactory . CreateInstance ( resourceType ) ;
105
+ AssignStringId ( identity , resource , state ) ;
106
+ resource . LocalId = identity . Lid ;
107
+ return resource ;
108
+ }
109
+
151
110
private static void AssertHasNoLid ( IResourceIdentity identity , RequestAdapterState state )
152
111
{
153
112
if ( identity . Lid != null )
@@ -165,14 +124,25 @@ private static void AssertNoIdWithLid(IResourceIdentity identity, RequestAdapter
165
124
}
166
125
}
167
126
168
- private static void AssertHasIdOrLid ( IResourceIdentity identity , RequestAdapterState state )
127
+ private static void AssertHasIdOrLid ( IResourceIdentity identity , ResourceIdentityRequirements requirements , RequestAdapterState state )
169
128
{
170
- if ( identity . Id == null && identity . Lid == null )
129
+ string message = null ;
130
+
131
+ if ( requirements . IdValue != null && identity . Id == null )
132
+ {
133
+ message = "The 'id' element is required." ;
134
+ }
135
+ else if ( requirements . LidValue != null && identity . Lid == null )
171
136
{
172
- string message = state . Request . Kind == EndpointKind . AtomicOperations
173
- ? "The 'id' or 'lid' element is required."
174
- : "The 'id' element is required." ;
137
+ message = "The 'lid' element is required." ;
138
+ }
139
+ else if ( identity . Id == null && identity . Lid == null )
140
+ {
141
+ message = state . Request . Kind == EndpointKind . AtomicOperations ? "The 'id' or 'lid' element is required." : "The 'id' element is required." ;
142
+ }
175
143
144
+ if ( message != null )
145
+ {
176
146
throw new ModelConversionException ( state . Position , message , null ) ;
177
147
}
178
148
}
@@ -186,18 +156,39 @@ private static void AssertHasNoId(IResourceIdentity identity, RequestAdapterStat
186
156
}
187
157
}
188
158
189
- private void AssignStringId ( IResourceIdentity identity , IIdentifiable resource , RequestAdapterState state )
159
+ private static void AssertSameIdValue ( IResourceIdentity identity , string expected , RequestAdapterState state )
190
160
{
191
- if ( identity . Id != null )
161
+ if ( expected != null && identity . Id != expected )
192
162
{
193
163
using IDisposable _ = state . Position . PushElement ( "id" ) ;
194
164
165
+ throw new ModelConversionException ( state . Position , "Conflicting 'id' values found." , $ "Expected '{ expected } ' instead of '{ identity . Id } '.",
166
+ HttpStatusCode . Conflict ) ;
167
+ }
168
+ }
169
+
170
+ private static void AssertSameLidValue ( IResourceIdentity identity , string expected , RequestAdapterState state )
171
+ {
172
+ if ( expected != null && identity . Lid != expected )
173
+ {
174
+ using IDisposable _ = state . Position . PushElement ( "lid" ) ;
175
+
176
+ throw new ModelConversionException ( state . Position , "Conflicting 'lid' values found." , $ "Expected '{ expected } ' instead of '{ identity . Lid } '.",
177
+ HttpStatusCode . Conflict ) ;
178
+ }
179
+ }
180
+
181
+ private void AssignStringId ( IResourceIdentity identity , IIdentifiable resource , RequestAdapterState state )
182
+ {
183
+ if ( identity . Id != null )
184
+ {
195
185
try
196
186
{
197
187
resource . StringId = identity . Id ;
198
188
}
199
189
catch ( FormatException exception )
200
190
{
191
+ using IDisposable _ = state . Position . PushElement ( "id" ) ;
201
192
throw new DeserializationException ( state . Position , null , exception . Message ) ;
202
193
}
203
194
}
0 commit comments