1
1
using System ;
2
+ using System . Collections ;
2
3
using System . IO ;
3
4
using System . Threading . Tasks ;
4
5
using JsonApiDotNetCore . Internal ;
6
+ using JsonApiDotNetCore . Models ;
5
7
using JsonApiDotNetCore . Serialization ;
6
8
using JsonApiDotNetCore . Services ;
7
9
using Microsoft . AspNetCore . Mvc . Formatters ;
@@ -37,7 +39,7 @@ public Task<InputFormatterResult> ReadAsync(InputFormatterContext context)
37
39
{
38
40
var body = GetRequestBody ( context . HttpContext . Request . Body ) ;
39
41
40
- object model = null ;
42
+ object model = null ;
41
43
42
44
if ( _jsonApiContext . IsRelationshipPath )
43
45
{
@@ -48,10 +50,29 @@ public Task<InputFormatterResult> ReadAsync(InputFormatterContext context)
48
50
model = _deSerializer . Deserialize ( body ) ;
49
51
}
50
52
53
+
51
54
if ( model == null )
52
55
{
53
56
_logger ? . LogError ( "An error occurred while de-serializing the payload" ) ;
54
57
}
58
+
59
+ if ( context . HttpContext . Request . Method == "PATCH" )
60
+ {
61
+ bool idMissing ;
62
+ if ( model is IList list )
63
+ {
64
+ idMissing = CheckForId ( list ) ;
65
+ }
66
+ else
67
+ {
68
+ idMissing = CheckForId ( model ) ;
69
+ }
70
+ if ( idMissing )
71
+ {
72
+ _logger ? . LogError ( "Payload must include id attribute" ) ;
73
+ throw new JsonApiException ( 400 , "Payload must include id attribute" ) ;
74
+ }
75
+ }
55
76
return InputFormatterResult . SuccessAsync ( model ) ;
56
77
}
57
78
catch ( Exception ex )
@@ -62,6 +83,40 @@ public Task<InputFormatterResult> ReadAsync(InputFormatterContext context)
62
83
}
63
84
}
64
85
86
+ /// <summary> Checks if the deserialized payload has an ID included </summary
87
+ private bool CheckForId ( object model )
88
+ {
89
+ if ( model == null ) return false ;
90
+ if ( model is ResourceObject ro )
91
+ {
92
+ if ( string . IsNullOrEmpty ( ro . Id ) ) return true ;
93
+ }
94
+ else if ( model is IIdentifiable identifiable )
95
+ {
96
+ if ( string . IsNullOrEmpty ( identifiable . StringId ) ) return true ;
97
+ }
98
+ return false ;
99
+ }
100
+
101
+ /// <summary> Checks if the elements in the deserialized payload have an ID included </summary
102
+ private bool CheckForId ( IList modelList )
103
+ {
104
+ foreach ( var model in modelList )
105
+ {
106
+ if ( model == null ) continue ;
107
+ if ( model is ResourceObject ro )
108
+ {
109
+ if ( string . IsNullOrEmpty ( ro . Id ) ) return true ;
110
+ }
111
+ else if ( model is IIdentifiable identifiable )
112
+ {
113
+ if ( string . IsNullOrEmpty ( identifiable . StringId ) ) return true ;
114
+ }
115
+ }
116
+ return false ;
117
+
118
+ }
119
+
65
120
private string GetRequestBody ( Stream body )
66
121
{
67
122
using ( var reader = new StreamReader ( body ) )
0 commit comments