33using System ;
44using System . Buffers ;
55using System . IO ;
6+ using System . Linq ;
67using System . Text ;
78using System . Threading . Tasks ;
9+ using Microsoft . AspNetCore . Http ;
810using Microsoft . AspNetCore . Mvc . Formatters ;
911using Newtonsoft . Json ;
1012using PartialResponse . AspNetCore . Mvc . Formatters . Json . Internal ;
13+ using PartialResponse . Core ;
1114
1215namespace PartialResponse . AspNetCore . Mvc . Formatters
1316{
@@ -61,26 +64,6 @@ public PartialJsonOutputFormatter(JsonSerializerSettings serializerSettings, Arr
6164 /// </remarks>
6265 protected JsonSerializerSettings SerializerSettings { get ; }
6366
64- /// <summary>
65- /// Writes the given <paramref name="value"/> as JSON using the given
66- /// <paramref name="writer"/>.
67- /// </summary>
68- /// <param name="writer">The <see cref="TextWriter"/> used to write the <paramref name="value"/></param>
69- /// <param name="value">The value to write as JSON.</param>
70- public void WriteObject ( TextWriter writer , object value )
71- {
72- if ( writer == null )
73- {
74- throw new ArgumentNullException ( nameof ( writer ) ) ;
75- }
76-
77- using ( var jsonWriter = CreateJsonWriter ( writer ) )
78- {
79- var jsonSerializer = CreateJsonSerializer ( ) ;
80- jsonSerializer . Serialize ( jsonWriter , value ) ;
81- }
82- }
83-
8467 /// <summary>
8568 /// Called during serialization to create the <see cref="JsonWriter"/>.
8669 /// </summary>
@@ -116,6 +99,62 @@ protected virtual JsonSerializer CreateJsonSerializer()
11699 return _serializer ;
117100 }
118101
102+ /// <summary>
103+ /// Gets a list of partial response fields for the current request.
104+ /// </summary>
105+ /// <param name="request">The request.</param>
106+ /// <returns>A <see cref="System.Collections.ObjectModel.Collection{string}"/> that contains the specified fields for the
107+ /// current request, or null if all fields should by serialized.</returns>
108+ protected virtual Fields GetPartialResponseFields ( HttpRequest request )
109+ {
110+ if ( request == null )
111+ {
112+ throw new ArgumentNullException ( "request" ) ;
113+ }
114+
115+ var queryOption = request . Query [ "fields" ] . FirstOrDefault ( ) ;
116+
117+ if ( queryOption != null )
118+ {
119+ Fields fields ;
120+
121+ if ( ! Fields . TryParse ( queryOption , out fields ) )
122+ {
123+ // TODO: No more HttpResponseException in ASP.NET Core.
124+ throw new Exception ( ) ;
125+ }
126+
127+ return fields ;
128+ }
129+
130+ return null ;
131+ }
132+
133+ /// <summary>
134+ /// Returns a value that indicates whether partial response should be bypassed.
135+ /// </summary>
136+ /// <param name="request">The request.</param>
137+ /// <returns>True if the partial response should be bypassed, otherwise false.</returns>
138+ protected virtual bool ShouldBypassPartialResponse ( HttpRequest request )
139+ {
140+ if ( request == null )
141+ {
142+ throw new ArgumentNullException ( "request" ) ;
143+ }
144+
145+ if ( request . GetBypassPartialResponse ( ) )
146+ {
147+ return true ;
148+ }
149+
150+ if ( request . HttpContext != null )
151+ {
152+ return request . HttpContext . Response . StatusCode != 200 ;
153+ }
154+
155+ return false ;
156+ }
157+
119158 /// <inheritdoc />
120159 public override async Task WriteResponseBodyAsync ( OutputFormatterWriteContext context , Encoding selectedEncoding )
121160 {
@@ -132,7 +171,26 @@ public override async Task WriteResponseBodyAsync(OutputFormatterWriteContext co
132171 var response = context . HttpContext . Response ;
133172 using ( var writer = context . WriterFactory ( response . Body , selectedEncoding ) )
134173 {
135- WriteObject ( writer , context . Object ) ;
174+ using ( var jsonWriter = CreateJsonWriter ( writer ) )
175+ {
176+ var jsonSerializer = CreateJsonSerializer ( ) ;
177+
178+ Fields fields = null ;
179+
180+ if ( ! ShouldBypassPartialResponse ( context . HttpContext . Request ) )
181+ {
182+ fields = GetPartialResponseFields ( context . HttpContext . Request ) ;
183+ }
184+
185+ if ( fields == null )
186+ {
187+ jsonSerializer . Serialize ( jsonWriter , context . Object ) ;
188+ }
189+ else
190+ {
191+ PartialJsonUtilities . RemovePropertiesAndArrayElements ( context . Object , jsonWriter , jsonSerializer , value => fields . Matches ( value ) ) ;
192+ }
193+ }
136194
137195 // Perf: call FlushAsync to call WriteAsync on the stream with any content left in the TextWriter's
138196 // buffers. This is better than just letting dispose handle it (which would result in a synchronous
0 commit comments