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
|
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.ComponentModel;
using System.Net.Http.Formatting;
using System.Net.Http.Headers;
using System.Threading.Tasks;
namespace System.Net.Http
{
/// <summary>
/// Extension methods to allow strongly typed objects to be read from <see cref="HttpContent"/> instances.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
public static class HttpContentExtensions
{
/// <summary>
/// Returns a <see cref="Task"/> that will yield an object of the specified <paramref name="type"/>
/// from the <paramref name="content"/> instance.
/// </summary>
/// <remarks>This override use the built-in collection of formatters.</remarks>
/// <param name="content">The <see cref="HttpContent"/> instance from which to read.</param>
/// <param name="type">The type of the object to read.</param>
/// <returns>A <see cref="Task"/> that will yield an object instance of the specified type.</returns>
public static Task<object> ReadAsAsync(this HttpContent content, Type type)
{
return content.ReadAsAsync(type, new MediaTypeFormatterCollection());
}
/// <summary>
/// Returns a <see cref="Task"/> that will yield an object of the specified <paramref name="type"/>
/// from the <paramref name="content"/> instance using one of the provided <paramref name="formatters"/>
/// to deserialize the content.
/// </summary>
/// <param name="content">The <see cref="HttpContent"/> instance from which to read.</param>
/// <param name="type">The type of the object to read.</param>
/// <param name="formatters">The collection of <see cref="MediaTypeFormatter"/> instances to use.</param>
/// <returns>An object instance of the specified type.</returns>
public static Task<object> ReadAsAsync(this HttpContent content, Type type, IEnumerable<MediaTypeFormatter> formatters)
{
return ReadAsAsync<object>(content, type, formatters, null);
}
/// <summary>
/// Returns a <see cref="Task"/> that will yield an object of the specified <paramref name="type"/>
/// from the <paramref name="content"/> instance using one of the provided <paramref name="formatters"/>
/// to deserialize the content.
/// </summary>
/// <param name="content">The <see cref="HttpContent"/> instance from which to read.</param>
/// <param name="type">The type of the object to read.</param>
/// <param name="formatters">The collection of <see cref="MediaTypeFormatter"/> instances to use.</param>
/// <param name="formatterLogger">The <see cref="IFormatterLogger"/> to log events to.</param>
/// <returns>An object instance of the specified type.</returns>
public static Task<object> ReadAsAsync(this HttpContent content, Type type, IEnumerable<MediaTypeFormatter> formatters, IFormatterLogger formatterLogger)
{
return ReadAsAsync<object>(content, type, formatters, formatterLogger);
}
/// <summary>
/// Returns a <see cref="Task"/> that will yield an object of the specified
/// type <typeparamref name="T"/> from the <paramref name="content"/> instance.
/// </summary>
/// <remarks>This override use the built-in collection of formatters.</remarks>
/// <typeparam name="T">The type of the object to read.</typeparam>
/// <param name="content">The <see cref="HttpContent"/> instance from which to read.</param>
/// <returns>An object instance of the specified type.</returns>
public static Task<T> ReadAsAsync<T>(this HttpContent content)
{
return content.ReadAsAsync<T>(new MediaTypeFormatterCollection());
}
/// <summary>
/// Returns a <see cref="Task"/> that will yield an object of the specified
/// type <typeparamref name="T"/> from the <paramref name="content"/> instance.
/// </summary>
/// <typeparam name="T">The type of the object to read.</typeparam>
/// <param name="content">The <see cref="HttpContent"/> instance from which to read.</param>
/// <param name="formatters">The collection of <see cref="MediaTypeFormatter"/> instances to use.</param>
/// <returns>An object instance of the specified type.</returns>
public static Task<T> ReadAsAsync<T>(this HttpContent content, IEnumerable<MediaTypeFormatter> formatters)
{
return ReadAsAsync<T>(content, typeof(T), formatters, null);
}
/// <summary>
/// Returns a <see cref="Task"/> that will yield an object of the specified
/// type <typeparamref name="T"/> from the <paramref name="content"/> instance.
/// </summary>
/// <typeparam name="T">The type of the object to read.</typeparam>
/// <param name="content">The <see cref="HttpContent"/> instance from which to read.</param>
/// <param name="formatters">The collection of <see cref="MediaTypeFormatter"/> instances to use.</param>
/// <param name="formatterLogger">The <see cref="IFormatterLogger"/> to log events to.</param>
/// <returns>An object instance of the specified type.</returns>
public static Task<T> ReadAsAsync<T>(this HttpContent content, IEnumerable<MediaTypeFormatter> formatters, IFormatterLogger formatterLogger)
{
return ReadAsAsync<T>(content, typeof(T), formatters, formatterLogger);
}
// There are many helper overloads for ReadAs*(). Provide one worker function to ensure the logic is shared.
//
// For loosely typed, T = Object, type = specific class.
// For strongly typed, T == type.GetType()
private static Task<T> ReadAsAsync<T>(HttpContent content, Type type, IEnumerable<MediaTypeFormatter> formatters, IFormatterLogger formatterLogger)
{
if (content == null)
{
throw new ArgumentNullException("content");
}
if (type == null)
{
throw new ArgumentNullException("type");
}
if (formatters == null)
{
throw new ArgumentNullException("formatters");
}
ObjectContent objectContent = content as ObjectContent;
if (objectContent != null && objectContent.Value != null && type.IsAssignableFrom(objectContent.Value.GetType()))
{
return TaskHelpers.FromResult((T)objectContent.Value);
}
MediaTypeFormatter formatter = null;
MediaTypeHeaderValue mediaType = content.Headers.ContentType;
if (mediaType != null)
{
formatter = new MediaTypeFormatterCollection(formatters).FindReader(type, mediaType);
}
if (formatter == null)
{
string mediaTypeAsString = mediaType != null ? mediaType.MediaType : Properties.Resources.UndefinedMediaType;
throw new InvalidOperationException(
RS.Format(Properties.Resources.NoReadSerializerAvailable, type.Name, mediaTypeAsString));
}
return content.ReadAsStreamAsync()
.Then(stream => formatter.ReadFromStreamAsync(type, stream, content.Headers, formatterLogger)
.Then(value => (T)value));
}
}
}
|