forked from aspnet/AspNetWebStack
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathJsonResult.cs
More file actions
153 lines (134 loc) · 5.91 KB
/
JsonResult.cs
File metadata and controls
153 lines (134 loc) · 5.91 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
using System.Globalization;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Newtonsoft.Json;
namespace System.Web.Http.Results
{
/// <summary>
/// Represents an action result that returns an <see cref="HttpStatusCode.OK"/> response with JSON data.
/// </summary>
/// <typeparam name="T">The type of content in the entity body.</typeparam>
public class JsonResult<T> : IHttpActionResult
{
private readonly T _content;
private readonly JsonSerializerSettings _serializerSettings;
private readonly Encoding _encoding;
private readonly StatusCodeResult.IDependencyProvider _dependencies;
/// <summary>
/// Initializes a new instance of the <see cref="JsonResult{T}"/> class with the values provided.
/// </summary>
/// <param name="content">The content value to serialize in the entity body.</param>
/// <param name="serializerSettings">The serializer settings.</param>
/// <param name="encoding">The content encoding.</param>
/// <param name="request">The request message which led to this result.</param>
public JsonResult(T content, JsonSerializerSettings serializerSettings, Encoding encoding,
HttpRequestMessage request)
: this(content, serializerSettings, encoding, new StatusCodeResult.DirectDependencyProvider(request))
{
}
/// <summary>
/// Initializes a new instance of the <see cref="JsonResult{T}"/> class with the values provided.
/// </summary>
/// <param name="content">The content value to serialize in the entity body.</param>
/// <param name="serializerSettings">The serializer settings.</param>
/// <param name="encoding">The content encoding.</param>
/// <param name="controller">The controller from which to obtain the dependencies needed for execution.</param>
public JsonResult(T content, JsonSerializerSettings serializerSettings, Encoding encoding,
ApiController controller)
: this(content, serializerSettings, encoding, new StatusCodeResult.ApiControllerDependencyProvider(
controller))
{
}
private JsonResult(T content, JsonSerializerSettings serializerSettings, Encoding encoding,
StatusCodeResult.IDependencyProvider dependencies)
{
if (serializerSettings == null)
{
throw new ArgumentNullException("serializerSettings");
}
if (encoding == null)
{
throw new ArgumentNullException("encoding");
}
Contract.Assert(dependencies != null);
_content = content;
_serializerSettings = serializerSettings;
_encoding = encoding;
_dependencies = dependencies;
}
/// <summary>Gets the content value to serialize in the entity body.</summary>
public T Content
{
get { return _content; }
}
/// <summary>Gets the serializer settings.</summary>
public JsonSerializerSettings SerializerSettings
{
get { return _serializerSettings; }
}
/// <summary>Gets the content encoding.</summary>
public Encoding Encoding
{
get { return _encoding; }
}
/// <summary>Gets the request message which led to this result.</summary>
public HttpRequestMessage Request
{
get { return _dependencies.Request; }
}
/// <inheritdoc />
public virtual Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
return Task.FromResult(Execute());
}
private HttpResponseMessage Execute()
{
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
try
{
ArraySegment<byte> segment = Serialize();
response.Content = new ByteArrayContent(segment.Array, segment.Offset, segment.Count);
MediaTypeHeaderValue contentType = new MediaTypeHeaderValue("application/json");
contentType.CharSet = _encoding.WebName;
response.Content.Headers.ContentType = contentType;
response.RequestMessage = _dependencies.Request;
}
catch
{
response.Dispose();
throw;
}
return response;
}
[SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times", Justification =
"False positive; specifying leaveOpen: true and CloseOutput=false prevents this condition.")]
private ArraySegment<byte> Serialize()
{
JsonSerializer serializer = JsonSerializer.Create(_serializerSettings);
using (MemoryStream stream = new MemoryStream())
{
const int DefaultStreamWriterBufferSize = 0x400;
using (TextWriter textWriter = new StreamWriter(stream, _encoding,
bufferSize: DefaultStreamWriterBufferSize, leaveOpen: true))
{
using (JsonWriter jsonWriter = new JsonTextWriter(textWriter) { CloseOutput = false })
{
serializer.Serialize(jsonWriter, _content);
jsonWriter.Flush();
}
}
Contract.Assert(stream.Length <= Int32.MaxValue);
return new ArraySegment<byte>(stream.GetBuffer(), 0, (int)stream.Length);
}
}
}
}