├── .gitignore ├── LICENSE ├── Marvin.StreamExtensions.sln ├── README.md ├── Test └── Marvin.StreamExtensions.Test │ └── Marvin.StreamExtensions.Test.csproj ├── src └── Marvin.StreamExtensions │ ├── Defaults.cs │ ├── Marvin.StreamExtensions.csproj │ ├── ResponseMessageExtensionsAsync.cs │ ├── StreamExtensions.cs │ └── StreamExtensionsAsync.cs └── test └── Marvin.StreamExtensions.Test ├── Marvin.StreamExtensions.Test.csproj ├── Person.cs ├── ResponseMessageTests.cs └── StreamTests.cs /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | [Xx]64/ 19 | [Xx]86/ 20 | [Bb]uild/ 21 | bld/ 22 | [Bb]in/ 23 | [Oo]bj/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | artifacts/ 46 | 47 | *_i.c 48 | *_p.c 49 | *_i.h 50 | *.ilk 51 | *.meta 52 | *.obj 53 | *.pch 54 | *.pdb 55 | *.pgc 56 | *.pgd 57 | *.rsp 58 | *.sbr 59 | *.tlb 60 | *.tli 61 | *.tlh 62 | *.tmp 63 | *.tmp_proj 64 | *.log 65 | *.vspscc 66 | *.vssscc 67 | .builds 68 | *.pidb 69 | *.svclog 70 | *.scc 71 | 72 | # Chutzpah Test files 73 | _Chutzpah* 74 | 75 | # Visual C++ cache files 76 | ipch/ 77 | *.aps 78 | *.ncb 79 | *.opendb 80 | *.opensdf 81 | *.sdf 82 | *.cachefile 83 | *.VC.db 84 | 85 | # Visual Studio profiler 86 | *.psess 87 | *.vsp 88 | *.vspx 89 | *.sap 90 | 91 | # TFS 2012 Local Workspace 92 | $tf/ 93 | 94 | # Guidance Automation Toolkit 95 | *.gpState 96 | 97 | # ReSharper is a .NET coding add-in 98 | _ReSharper*/ 99 | *.[Rr]e[Ss]harper 100 | *.DotSettings.user 101 | 102 | # JustCode is a .NET coding add-in 103 | .JustCode 104 | 105 | # TeamCity is a build add-in 106 | _TeamCity* 107 | 108 | # DotCover is a Code Coverage Tool 109 | *.dotCover 110 | 111 | # NCrunch 112 | _NCrunch_* 113 | .*crunch*.local.xml 114 | nCrunchTemp_* 115 | 116 | # MightyMoose 117 | *.mm.* 118 | AutoTest.Net/ 119 | 120 | # Web workbench (sass) 121 | .sass-cache/ 122 | 123 | # Installshield output folder 124 | [Ee]xpress/ 125 | 126 | # DocProject is a documentation generator add-in 127 | DocProject/buildhelp/ 128 | DocProject/Help/*.HxT 129 | DocProject/Help/*.HxC 130 | DocProject/Help/*.hhc 131 | DocProject/Help/*.hhk 132 | DocProject/Help/*.hhp 133 | DocProject/Help/Html2 134 | DocProject/Help/html 135 | 136 | # Click-Once directory 137 | publish/ 138 | 139 | # Publish Web Output 140 | *.[Pp]ublish.xml 141 | *.azurePubxml 142 | 143 | # TODO: Un-comment the next line if you do not want to checkin 144 | # your web deploy settings because they may include unencrypted 145 | # passwords 146 | #*.pubxml 147 | *.publishproj 148 | 149 | # NuGet Packages 150 | *.nupkg 151 | # The packages folder can be ignored because of Package Restore 152 | **/packages/* 153 | # except build/, which is used as an MSBuild target. 154 | !**/packages/build/ 155 | # Uncomment if necessary however generally it will be regenerated when needed 156 | #!**/packages/repositories.config 157 | # NuGet v3's project.json files produces more ignoreable files 158 | *.nuget.props 159 | *.nuget.targets 160 | 161 | # Microsoft Azure Build Output 162 | csx/ 163 | *.build.csdef 164 | 165 | # Microsoft Azure Emulator 166 | ecf/ 167 | rcf/ 168 | 169 | # Microsoft Azure ApplicationInsights config file 170 | ApplicationInsights.config 171 | 172 | # Windows Store app package directory 173 | AppPackages/ 174 | BundleArtifacts/ 175 | 176 | # Visual Studio cache files 177 | # files ending in .cache can be ignored 178 | *.[Cc]ache 179 | # but keep track of directories ending in .cache 180 | !*.[Cc]ache/ 181 | 182 | # Others 183 | ClientBin/ 184 | [Ss]tyle[Cc]op.* 185 | ~$* 186 | *~ 187 | *.dbmdl 188 | *.dbproj.schemaview 189 | *.pfx 190 | *.publishsettings 191 | node_modules/ 192 | orleans.codegen.cs 193 | 194 | # RIA/Silverlight projects 195 | Generated_Code/ 196 | 197 | # Backup & report files from converting an old project file 198 | # to a newer Visual Studio version. Backup files are not needed, 199 | # because we have git ;-) 200 | _UpgradeReport_Files/ 201 | Backup*/ 202 | UpgradeLog*.XML 203 | UpgradeLog*.htm 204 | 205 | # SQL Server files 206 | *.mdf 207 | *.ldf 208 | 209 | # Business Intelligence projects 210 | *.rdl.data 211 | *.bim.layout 212 | *.bim_*.settings 213 | 214 | # Microsoft Fakes 215 | FakesAssemblies/ 216 | 217 | # GhostDoc plugin setting file 218 | *.GhostDoc.xml 219 | 220 | # Node.js Tools for Visual Studio 221 | .ntvs_analysis.dat 222 | 223 | # Visual Studio 6 build log 224 | *.plg 225 | 226 | # Visual Studio 6 workspace options file 227 | *.opt 228 | 229 | # Visual Studio LightSwitch build output 230 | **/*.HTMLClient/GeneratedArtifacts 231 | **/*.DesktopClient/GeneratedArtifacts 232 | **/*.DesktopClient/ModelManifest.xml 233 | **/*.Server/GeneratedArtifacts 234 | **/*.Server/ModelManifest.xml 235 | _Pvt_Extensions 236 | 237 | # LightSwitch generated files 238 | GeneratedArtifacts/ 239 | ModelManifest.xml 240 | 241 | # Paket dependency manager 242 | .paket/paket.exe 243 | 244 | # FAKE - F# Make 245 | .fake/ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Kevin Dockx 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Marvin.StreamExtensions.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28010.2026 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Marvin.StreamExtensions.Test", "Test\Marvin.StreamExtensions.Test\Marvin.StreamExtensions.Test.csproj", "{3E3631EA-DB99-4F15-B0BD-411792BD4C17}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Marvin.StreamExtensions", "src\Marvin.StreamExtensions\Marvin.StreamExtensions.csproj", "{FEACFB0D-6410-4C36-8EC9-0014FA2E4C44}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {3E3631EA-DB99-4F15-B0BD-411792BD4C17}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {3E3631EA-DB99-4F15-B0BD-411792BD4C17}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {3E3631EA-DB99-4F15-B0BD-411792BD4C17}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {3E3631EA-DB99-4F15-B0BD-411792BD4C17}.Release|Any CPU.Build.0 = Release|Any CPU 20 | {FEACFB0D-6410-4C36-8EC9-0014FA2E4C44}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {FEACFB0D-6410-4C36-8EC9-0014FA2E4C44}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {FEACFB0D-6410-4C36-8EC9-0014FA2E4C44}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {FEACFB0D-6410-4C36-8EC9-0014FA2E4C44}.Release|Any CPU.Build.0 = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {4B7AC53D-3776-49A2-9614-10AA469D1A63} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Stream Extensions 2 | A set of helper extension methods (on Stream) for working with streams. Particularly useful for interaction with an API through HttpClient. Includes 24 extension methods in total (sync & async where it makes sense, generic & non-generic) like `SerializeToJsonAndWriteAsync`, `SerializeToJsonAndWrite` and `ReadAndDeserializeFromJson`. 3 | 4 | [![NuGet version](https://badge.fury.io/nu/Marvin.StreamExtensions.svg)](https://badge.fury.io/nu/Marvin.StreamExtensions) 5 | 6 | # Installation (NuGet) 7 | ``` 8 | Install-Package Marvin.StreamExtensions 9 | ``` 10 | 11 | # Usage 12 | 13 | Add a using statement to import the extension methods 14 | ``` 15 | using Marvin.StreamExtensions 16 | ``` 17 | 18 | From this moment on any Stream object will have a set of additional extension methods available. 19 | 20 | To deserialize the response of an HttpRequest from Json, using streams: 21 | 22 | ``` 23 | using (var response = await httpClient.SendAsync(request)) 24 | { 25 | using (var stream = await response.Content.ReadAsStreamAsync()) 26 | { 27 | var person = stream.ReadAndDeserializeFromJson(); 28 | } 29 | } 30 | ``` 31 | 32 | To use a stream for sending data: 33 | 34 | ``` 35 | var person = new Person() { Name = "Lord Flashheart" }; 36 | var memoryContentStream = new MemoryStream(); 37 | memoryContentStream.SerializeToJsonAndWrite(person); 38 | 39 | using (var request = new HttpRequestMessage( 40 | HttpMethod.Post, 41 | "http://api/test")) 42 | { 43 | request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); 44 | using (var streamContent = new StreamContent(memoryContentStream)) 45 | { 46 | streamContent.Headers.ContentType = new MediaTypeHeaderValue("application/json"); 47 | request.Content = streamContent; 48 | 49 | using (var response = await httpClient.SendAsync(request)) 50 | { 51 | // handle the response 52 | } 53 | } 54 | } 55 | ``` 56 | -------------------------------------------------------------------------------- /Test/Marvin.StreamExtensions.Test/Marvin.StreamExtensions.Test.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp2.1 5 | 6 | false 7 | 8 | 9 | 10 | latest 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/Marvin.StreamExtensions/Defaults.cs: -------------------------------------------------------------------------------- 1 | namespace Marvin.StreamExtensions 2 | { 3 | internal static class Defaults 4 | { 5 | internal static int DefaultBufferSizeOnRead { get; } = 1024; 6 | internal static int DefaultBufferSizeOnWrite { get; } = 1024; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/Marvin.StreamExtensions/Marvin.StreamExtensions.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netstandard2.0 5 | Kevin Dockx 6 | Marvin 7 | A set of helper extension methods (on Stream) for working with streams. Particularly useful for interaction with an API through HttpClient. 8 | 9 | 10 | 11 | latest 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/Marvin.StreamExtensions/ResponseMessageExtensionsAsync.cs: -------------------------------------------------------------------------------- 1 | using System.Net.Http; 2 | using System.Text; 3 | using System.Threading.Tasks; 4 | 5 | namespace Marvin.StreamExtensions 6 | { 7 | public static class ResponseMessageExtensionsAsync 8 | { 9 | /// 10 | /// Reads content of HttpResponseMessage as a stream and deserializes into an object of type T (assuming Json content). 11 | /// 12 | /// The object type 13 | /// The HTTP response message 14 | /// An object of type T 15 | public static async Task DeserializeAsStreamAsync( 16 | this HttpResponseMessage message) 17 | { 18 | return await DeserializeAsStreamAsync( 19 | message, 20 | new UTF8Encoding(), 21 | true, 22 | Defaults.DefaultBufferSizeOnRead, 23 | false); 24 | } 25 | 26 | /// 27 | /// Reads content of HttpResponseMessage as a stream and deserializes into an object of type T (assuming Json content). 28 | /// 29 | /// The object type 30 | /// The HTTP response message 31 | /// The encoding to use 32 | /// An object of type T 33 | public static async Task DeserializeAsStreamAsync( 34 | this HttpResponseMessage message, 35 | Encoding encoding) 36 | { 37 | return await DeserializeAsStreamAsync( 38 | message, 39 | encoding, 40 | true, 41 | Defaults.DefaultBufferSizeOnRead, 42 | false); 43 | } 44 | 45 | /// 46 | /// Reads content of HttpResponseMessage as a stream and deserializes into an object of type T (assuming Json content). 47 | /// 48 | /// The object type 49 | /// The HTTP response message 50 | /// True to detect encoding from byte order marks, false otherwise 51 | /// An object of type T 52 | public static async Task DeserializeAsStreamAsync( 53 | this HttpResponseMessage message, 54 | bool detectEncodingFromByteOrderMarks) 55 | { 56 | return await DeserializeAsStreamAsync( 57 | message, 58 | new UTF8Encoding(), 59 | detectEncodingFromByteOrderMarks, 60 | Defaults.DefaultBufferSizeOnRead, 61 | false); 62 | } 63 | 64 | /// 65 | /// Reads content of HttpResponseMessage as a stream and deserializes into an object of type T (assuming Json content). 66 | /// 67 | /// The object type 68 | /// The HTTP response message 69 | /// The encoding to use 70 | /// True to detect encoding from byte order marks, false otherwise 71 | /// The size of the buffer 72 | /// An object of type T 73 | public static async Task DeserializeAsStreamAsync( 74 | this HttpResponseMessage message, 75 | Encoding encoding, 76 | bool detectEncodingFromByteOrderMarks, 77 | int bufferSize) 78 | { 79 | return await DeserializeAsStreamAsync( 80 | message, 81 | encoding, 82 | detectEncodingFromByteOrderMarks, 83 | bufferSize, 84 | false); 85 | } 86 | 87 | /// 88 | /// Reads content of HttpResponseMessage as a stream and deserializes into an object of type T (assuming Json content). 89 | /// 90 | /// The object type 91 | /// The HTTP response message 92 | /// The encoding to use 93 | /// True to detect encoding from byte order marks, false otherwise 94 | /// The size of the buffer 95 | /// True to leave the stream open after the (internally used) StreamReader object is disposed 96 | /// An object of type T 97 | public static async Task DeserializeAsStreamAsync( 98 | this HttpResponseMessage message, 99 | Encoding encoding, 100 | bool detectEncodingFromByteOrderMarks, 101 | int bufferSize, 102 | bool leaveOpen) 103 | { 104 | var stream = await message.Content.ReadAsStreamAsync(); 105 | return await stream.ReadAndDeserializeFromJsonAsync( 106 | encoding, 107 | detectEncodingFromByteOrderMarks, 108 | bufferSize, 109 | leaveOpen); 110 | } 111 | } 112 | } -------------------------------------------------------------------------------- /src/Marvin.StreamExtensions/StreamExtensions.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System; 3 | using System.IO; 4 | using System.Text; 5 | 6 | namespace Marvin.StreamExtensions 7 | { 8 | /// 9 | /// Extension methods for working with streams 10 | /// 11 | public static partial class StreamExtensions 12 | { 13 | /// 14 | /// Read from the stream and deserialize into an object of type T (assuming Json content). 15 | /// 16 | /// The object type 17 | /// The stream 18 | /// The JsonSerialization setting beeing used for serialization. In default state it will use default settings from Newtonsoft.Json.JsonConvert.DefaultSettings 19 | /// An object of type T 20 | public static T ReadAndDeserializeFromJson( 21 | this Stream stream, 22 | JsonSerializerSettings jsonSerializerSettings = default) 23 | { 24 | return ReadAndDeserializeFromJson(stream, new UTF8Encoding(), true, 25 | Defaults.DefaultBufferSizeOnRead, false, jsonSerializerSettings); 26 | } 27 | 28 | /// 29 | /// Read from the stream and deserialize into an object of type T (assuming Json content). 30 | /// 31 | /// The object type 32 | /// The stream 33 | /// The encoding to use 34 | /// The JsonSerialization setting beeing used for serialization. In default state it will use default settings from Newtonsoft.Json.JsonConvert.DefaultSettings 35 | /// An object of type T 36 | public static T ReadAndDeserializeFromJson( 37 | this Stream stream, 38 | Encoding encoding, 39 | JsonSerializerSettings jsonSerializerSettings = default) 40 | { 41 | return ReadAndDeserializeFromJson(stream, encoding, true, 42 | Defaults.DefaultBufferSizeOnRead, false, jsonSerializerSettings); 43 | } 44 | 45 | /// 46 | /// Read from the stream and deserialize into an object of type T (assuming Json content). 47 | /// 48 | /// The object type 49 | /// The stream 50 | /// True to detect encoding from byte order marks, false otherwise 51 | /// The JsonSerialization setting beeing used for serialization. In default state it will use default settings from Newtonsoft.Json.JsonConvert.DefaultSettings 52 | /// An object of type T 53 | public static T ReadAndDeserializeFromJson( 54 | this Stream stream, 55 | bool detectEncodingFromByteOrderMarks, 56 | JsonSerializerSettings jsonSerializerSettings = default) 57 | { 58 | return ReadAndDeserializeFromJson(stream, new UTF8Encoding(), 59 | detectEncodingFromByteOrderMarks, Defaults.DefaultBufferSizeOnRead, false, jsonSerializerSettings); 60 | } 61 | 62 | /// 63 | /// Read from the stream and deserialize into an object of type T (assuming Json content). 64 | /// 65 | /// The object type 66 | /// The stream 67 | /// The encoding to use 68 | /// True to detect encoding from byte order marks, false otherwise 69 | /// The size of the buffer 70 | /// The JsonSerialization setting beeing used for serialization. In default state it will use default settings from Newtonsoft.Json.JsonConvert.DefaultSettings 71 | /// An object of type T 72 | public static T ReadAndDeserializeFromJson( 73 | this Stream stream, 74 | Encoding encoding, 75 | bool detectEncodingFromByteOrderMarks, 76 | int bufferSize, 77 | JsonSerializerSettings jsonSerializerSettings = default) 78 | { 79 | return ReadAndDeserializeFromJson(stream, encoding, 80 | detectEncodingFromByteOrderMarks, bufferSize, false, jsonSerializerSettings); 81 | } 82 | 83 | /// 84 | /// Read from the stream and deserialize into an object of type T (assuming Json content). 85 | /// 86 | /// The object type 87 | /// The stream 88 | /// The encoding to use 89 | /// True to detect encoding from byte order marks, false otherwise 90 | /// The size of the buffer 91 | /// True to leave the stream open after the (internally used) StreamReader object is disposed 92 | /// The JsonSerialization setting beeing used for serialization. In default state it will use default settings from Newtonsoft.Json.JsonConvert.DefaultSettings 93 | /// An object of type T 94 | public static T ReadAndDeserializeFromJson( 95 | this Stream stream, 96 | Encoding encoding, 97 | bool detectEncodingFromByteOrderMarks, 98 | int bufferSize, 99 | bool leaveOpen, 100 | JsonSerializerSettings jsonSerializerSettings = default) 101 | { 102 | 103 | if (stream == null) 104 | { 105 | throw new ArgumentNullException(nameof(stream)); 106 | } 107 | 108 | if (!stream.CanRead) 109 | { 110 | throw new NotSupportedException("Can't read from this stream."); 111 | } 112 | 113 | if (encoding == null) 114 | { 115 | throw new ArgumentNullException(nameof(encoding)); 116 | } 117 | 118 | using var streamReader = new StreamReader(stream, encoding, detectEncodingFromByteOrderMarks, bufferSize, leaveOpen); 119 | using var jsonTextReader = new JsonTextReader(streamReader); 120 | var jsonSerializer = jsonSerializerSettings == default ? JsonSerializer.Create() : JsonSerializer.Create(jsonSerializerSettings); 121 | return jsonSerializer.Deserialize(jsonTextReader); 122 | } 123 | 124 | /// 125 | /// Read from the stream and deserialize (assuming Json content). 126 | /// 127 | /// The stream 128 | /// The JsonSerialization setting beeing used for serialization. In default state it will use default settings from Newtonsoft.Json.JsonConvert.DefaultSettings 129 | /// The deserialized object 130 | public static object ReadAndDeserializeFromJson( 131 | this Stream stream, 132 | JsonSerializerSettings jsonSerializerSettings = default) 133 | { 134 | return ReadAndDeserializeFromJson(stream, new UTF8Encoding(), true, 135 | Defaults.DefaultBufferSizeOnRead, jsonSerializerSettings); 136 | } 137 | 138 | /// 139 | /// Read from the stream and deserialize (assuming Json content). 140 | /// 141 | /// The stream 142 | /// The encoding to use 143 | /// The JsonSerialization setting beeing used for serialization. In default state it will use default settings from Newtonsoft.Json.JsonConvert.DefaultSettings 144 | /// The deserialized object 145 | public static object ReadAndDeserializeFromJson( 146 | this Stream stream, 147 | Encoding encoding, 148 | JsonSerializerSettings jsonSerializerSettings = default) 149 | { 150 | return ReadAndDeserializeFromJson(stream, encoding, true, 151 | Defaults.DefaultBufferSizeOnRead, false, jsonSerializerSettings); 152 | } 153 | 154 | /// 155 | /// Read from the stream and deserialize (assuming Json content). 156 | /// 157 | /// The stream 158 | /// True to detect encoding from byte order marks, false otherwise 159 | /// The JsonSerialization setting beeing used for serialization. In default state it will use default settings from Newtonsoft.Json.JsonConvert.DefaultSettings 160 | /// The deserialized object 161 | public static object ReadAndDeserializeFromJson( 162 | this Stream stream, 163 | bool detectEncodingFromByteOrderMarks, 164 | JsonSerializerSettings jsonSerializerSettings = default) 165 | { 166 | return ReadAndDeserializeFromJson(stream, new UTF8Encoding(), 167 | detectEncodingFromByteOrderMarks, Defaults.DefaultBufferSizeOnRead, false, jsonSerializerSettings); 168 | } 169 | 170 | 171 | /// 172 | /// Read from the stream and deserialize (assuming Json content). 173 | /// 174 | /// The stream 175 | /// The encoding to use 176 | /// True to detect encoding from byte order marks, false otherwise 177 | /// The size of the buffer 178 | /// The JsonSerialization setting beeing used for serialization. In default state it will use default settings from Newtonsoft.Json.JsonConvert.DefaultSettings 179 | /// The deserialized object 180 | public static object ReadAndDeserializeFromJson( 181 | this Stream stream, 182 | Encoding encoding, 183 | bool detectEncodingFromByteOrderMarks, 184 | int bufferSize, 185 | JsonSerializerSettings jsonSerializerSettings = default) 186 | { 187 | return ReadAndDeserializeFromJson(stream, encoding, 188 | detectEncodingFromByteOrderMarks, bufferSize, false, jsonSerializerSettings); 189 | } 190 | 191 | /// 192 | /// Read from the stream and deserialize (assuming Json content). 193 | /// 194 | /// The stream 195 | /// The encoding to use 196 | /// True to detect encoding from byte order marks, false otherwise 197 | /// The size of the buffer 198 | /// True to leave the stream open after the (internally used) StreamReader object is disposed 199 | /// The JsonSerialization setting beeing used for serialization. In default state it will use default settings from Newtonsoft.Json.JsonConvert.DefaultSettings 200 | /// The deserialized object 201 | public static object ReadAndDeserializeFromJson( 202 | this Stream stream, 203 | Encoding encoding, 204 | bool detectEncodingFromByteOrderMarks, 205 | int bufferSize, 206 | bool leaveOpen, 207 | JsonSerializerSettings jsonSerializerSettings = default) 208 | { 209 | if (stream == null) 210 | { 211 | throw new ArgumentNullException(nameof(stream)); 212 | } 213 | 214 | if (!stream.CanRead) 215 | { 216 | throw new NotSupportedException("Can't read from this stream."); 217 | } 218 | 219 | if (encoding == null) 220 | { 221 | throw new ArgumentNullException(nameof(encoding)); 222 | } 223 | 224 | using var streamReader = new StreamReader(stream, encoding, detectEncodingFromByteOrderMarks, bufferSize, leaveOpen); 225 | using var jsonTextReader = new JsonTextReader(streamReader); 226 | 227 | var jsonSerializer = jsonSerializerSettings == default ? JsonSerializer.Create() : JsonSerializer.Create(jsonSerializerSettings); 228 | return jsonSerializer.Deserialize(jsonTextReader); 229 | } 230 | 231 | /// 232 | /// Serialize (to Json) and write to the stream 233 | /// 234 | /// The type the object to serialize/write 235 | /// The stream 236 | /// The object to write to the stream 237 | /// The JsonSerialization setting beeing used for serialization. In default state it will use default settings from Newtonsoft.Json.JsonConvert.DefaultSettings 238 | public static void SerializeToJsonAndWrite( 239 | this Stream stream, 240 | T objectToWrite, 241 | JsonSerializerSettings jsonSerializerSettings = default) 242 | { 243 | SerializeToJsonAndWrite(stream, objectToWrite, new UTF8Encoding(), Defaults.DefaultBufferSizeOnWrite, false, false, jsonSerializerSettings); 244 | } 245 | 246 | /// 247 | /// Serialize (to Json) and write to the stream 248 | /// 249 | /// The type the object to serialize/write 250 | /// The stream 251 | /// The object to write to the stream 252 | /// The encoding to use 253 | /// The JsonSerialization setting beeing used for serialization. In default state it will use default settings from Newtonsoft.Json.JsonConvert.DefaultSettings 254 | public static void SerializeToJsonAndWrite( 255 | this Stream stream, 256 | T objectToWrite, 257 | Encoding encoding, 258 | JsonSerializerSettings jsonSerializerSettings = default) 259 | { 260 | SerializeToJsonAndWrite(stream, objectToWrite, encoding, Defaults.DefaultBufferSizeOnWrite, false, false, jsonSerializerSettings); 261 | } 262 | 263 | /// 264 | /// Serialize (to Json) and write to the stream 265 | /// 266 | /// The type the object to serialize/write 267 | /// The stream 268 | /// The object to write to the stream 269 | /// The encoding to use 270 | /// The size of the buffer 271 | /// The JsonSerialization setting beeing used for serialization. In default state it will use default settings from Newtonsoft.Json.JsonConvert.DefaultSettings 272 | public static void SerializeToJsonAndWrite( 273 | this Stream stream, 274 | T objectToWrite, 275 | Encoding encoding, 276 | int bufferSize, 277 | JsonSerializerSettings jsonSerializerSettings = default) 278 | { 279 | SerializeToJsonAndWrite(stream, objectToWrite, encoding, bufferSize, false, false, jsonSerializerSettings); 280 | } 281 | 282 | /// 283 | /// Serialize (to Json) and write to the stream 284 | /// 285 | /// The type the object to serialize/write 286 | /// The stream 287 | /// The object to write to the stream 288 | /// The encoding to use 289 | /// The size of the buffer 290 | /// True to leave the stream open after the (internally used) StreamWriter object is disposed 291 | /// The JsonSerialization setting beeing used for serialization. In default state it will use default settings from Newtonsoft.Json.JsonConvert.DefaultSettings 292 | public static void SerializeToJsonAndWrite( 293 | this Stream stream, 294 | T objectToWrite, 295 | Encoding encoding, 296 | int bufferSize, 297 | bool leaveOpen, 298 | JsonSerializerSettings jsonSerializerSettings = default) 299 | { 300 | SerializeToJsonAndWrite(stream, objectToWrite, encoding, bufferSize, leaveOpen, false, jsonSerializerSettings); 301 | } 302 | 303 | /// 304 | /// Serialize (to Json) and write to the stream 305 | /// 306 | /// The type the object to serialize/write 307 | /// The stream 308 | /// The object to write to the stream 309 | /// True to reset the stream to position 0 after writing, false otherwise 310 | /// The JsonSerialization setting beeing used for serialization. In default state it will use default settings from Newtonsoft.Json.JsonConvert.DefaultSettings 311 | public static void SerializeToJsonAndWrite( 312 | this Stream stream, 313 | T objectToWrite, 314 | bool resetStream, 315 | JsonSerializerSettings jsonSerializerSettings = default) 316 | { 317 | SerializeToJsonAndWrite(stream, objectToWrite, new UTF8Encoding(), Defaults.DefaultBufferSizeOnWrite, false, resetStream, jsonSerializerSettings); 318 | } 319 | 320 | /// 321 | /// Serialize (to Json) and write to the stream 322 | /// 323 | /// The type the object to serialize/write 324 | /// The stream 325 | /// The object to write to the stream 326 | /// The encoding to use 327 | /// True to reset the stream to position 0 after writing, false otherwise 328 | /// The JsonSerialization setting beeing used for serialization. In default state it will use default settings from Newtonsoft.Json.JsonConvert.DefaultSettings 329 | public static void SerializeToJsonAndWrite( 330 | this Stream stream, 331 | T objectToWrite, 332 | Encoding encoding, 333 | bool resetStream, JsonSerializerSettings jsonSerializerSettings = default) 334 | { 335 | SerializeToJsonAndWrite(stream, objectToWrite, encoding, Defaults.DefaultBufferSizeOnWrite, false, resetStream, jsonSerializerSettings); 336 | } 337 | 338 | /// 339 | /// Serialize (to Json) and write to the stream 340 | /// 341 | /// The type the object to serialize/write 342 | /// The stream 343 | /// The object to write to the stream 344 | /// The encoding to use 345 | /// The size of the buffer 346 | /// True to leave the stream open after the (internally used) StreamWriter object is disposed 347 | /// True to reset the stream to position 0 after writing, false otherwise 348 | /// The JsonSerialization setting beeing used for serialization. In default state it will use default settings from Newtonsoft.Json.JsonConvert.DefaultSettings 349 | public static void SerializeToJsonAndWrite( 350 | this Stream stream, 351 | T objectToWrite, 352 | Encoding encoding, 353 | int bufferSize, 354 | bool leaveOpen, 355 | bool resetStream, 356 | JsonSerializerSettings jsonSerializerSettings = default) 357 | { 358 | 359 | if (stream == null) 360 | { 361 | throw new ArgumentNullException(nameof(stream)); 362 | } 363 | 364 | if (!stream.CanWrite) 365 | { 366 | throw new NotSupportedException("Can't write to this stream."); 367 | } 368 | 369 | if (encoding == null) 370 | { 371 | throw new ArgumentNullException(nameof(encoding)); 372 | } 373 | 374 | using var streamWriter = new StreamWriter(stream, encoding, bufferSize, leaveOpen); 375 | using var jsonTextWriter = new JsonTextWriter(streamWriter); 376 | 377 | var jsonSerializer = jsonSerializerSettings == default ? JsonSerializer.Create() : JsonSerializer.Create(jsonSerializerSettings); 378 | jsonSerializer.Serialize(jsonTextWriter, objectToWrite); 379 | jsonTextWriter.Flush(); 380 | 381 | // after writing, set the stream to position 0 382 | if (resetStream && stream.CanSeek) 383 | { 384 | stream.Seek(0, SeekOrigin.Begin); 385 | } 386 | } 387 | 388 | /// 389 | /// Serialize (to Json) and write to the stream 390 | /// 391 | /// The stream 392 | /// The object to write to the stream 393 | /// The JsonSerialization setting beeing used for serialization. In default state it will use default settings from Newtonsoft.Json.JsonConvert.DefaultSettings 394 | public static void SerializeToJsonAndWrite( 395 | this Stream stream, 396 | object objectToWrite, 397 | JsonSerializerSettings jsonSerializerSettings = default) 398 | { 399 | SerializeToJsonAndWrite(stream, objectToWrite, new UTF8Encoding(), Defaults.DefaultBufferSizeOnWrite, false, false, jsonSerializerSettings); 400 | } 401 | 402 | /// 403 | /// Serialize (to Json) and write to the stream 404 | /// 405 | /// The stream 406 | /// The object to write to the stream 407 | /// The encoding to use 408 | /// The JsonSerialization setting beeing used for serialization. In default state it will use default settings from Newtonsoft.Json.JsonConvert.DefaultSettings 409 | public static void SerializeToJsonAndWrite( 410 | this Stream stream, 411 | object objectToWrite, 412 | Encoding encoding, 413 | JsonSerializerSettings jsonSerializerSettings = default) 414 | { 415 | SerializeToJsonAndWrite(stream, objectToWrite, encoding, Defaults.DefaultBufferSizeOnWrite, false, false, jsonSerializerSettings); 416 | } 417 | 418 | /// 419 | /// Serialize (to Json) and write to the stream 420 | /// 421 | /// The stream 422 | /// The object to write to the stream 423 | /// The encoding to use 424 | /// The size of the buffer 425 | /// The JsonSerialization setting beeing used for serialization. In default state it will use default settings from Newtonsoft.Json.JsonConvert.DefaultSettings 426 | public static void SerializeToJsonAndWrite( 427 | this Stream stream, 428 | object objectToWrite, 429 | Encoding encoding, 430 | int bufferSize, 431 | JsonSerializerSettings jsonSerializerSettings = default) 432 | { 433 | SerializeToJsonAndWrite(stream, objectToWrite, encoding, bufferSize, false, false, jsonSerializerSettings); 434 | } 435 | 436 | /// 437 | /// Serialize (to Json) and write to the stream 438 | /// 439 | /// The stream 440 | /// The object to write to the stream 441 | /// The encoding to use 442 | /// The size of the buffer 443 | /// True to leave the stream open after the (internally used) StreamWriter object is disposed 444 | /// The JsonSerialization setting beeing used for serialization. In default state it will use default settings from Newtonsoft.Json.JsonConvert.DefaultSettings 445 | public static void SerializeToJsonAndWrite( 446 | this Stream stream, 447 | object objectToWrite, 448 | Encoding encoding, 449 | int bufferSize, 450 | bool leaveOpen, 451 | JsonSerializerSettings jsonSerializerSettings = default) 452 | { 453 | SerializeToJsonAndWrite(stream, objectToWrite, encoding, bufferSize, leaveOpen, false, jsonSerializerSettings); 454 | } 455 | 456 | /// 457 | /// Serialize (to Json) and write to the stream 458 | /// 459 | /// The stream 460 | /// The object to write to the stream 461 | /// True to reset the stream to position 0 after writing, false otherwise 462 | /// The JsonSerialization setting beeing used for serialization. In default state it will use default settings from Newtonsoft.Json.JsonConvert.DefaultSettings 463 | public static void SerializeToJsonAndWrite( 464 | this Stream stream, 465 | object objectToWrite, 466 | bool resetStream, 467 | JsonSerializerSettings jsonSerializerSettings = default) 468 | { 469 | SerializeToJsonAndWrite(stream, objectToWrite, new UTF8Encoding(), Defaults.DefaultBufferSizeOnWrite, false, resetStream, jsonSerializerSettings); 470 | } 471 | 472 | /// 473 | /// Serialize (to Json) and write to the stream 474 | /// 475 | /// The stream 476 | /// The object to write to the stream 477 | /// The encoding to use 478 | /// True to reset the stream to position 0 after writing, false otherwise 479 | /// The JsonSerialization setting beeing used for serialization. In default state it will use default settings from Newtonsoft.Json.JsonConvert.DefaultSettings 480 | public static void SerializeToJsonAndWrite( 481 | this Stream stream, 482 | object objectToWrite, 483 | Encoding encoding, 484 | bool resetStream, 485 | JsonSerializerSettings jsonSerializerSettings = default) 486 | { 487 | SerializeToJsonAndWrite(stream, objectToWrite, encoding, Defaults.DefaultBufferSizeOnWrite, false, resetStream, jsonSerializerSettings); 488 | } 489 | 490 | /// 491 | /// Serialize (to Json) and write to the stream 492 | /// 493 | /// The stream 494 | /// The object to write to the stream 495 | /// The encoding to use 496 | /// The size of the buffer 497 | /// True to leave the stream open after the (internally used) StreamWriter object is disposed 498 | /// True to reset the stream to position 0 after writing, false otherwise 499 | /// The JsonSerialization setting beeing used for serialization. In default state it will use default settings from Newtonsoft.Json.JsonConvert.DefaultSettings 500 | public static void SerializeToJsonAndWrite( 501 | this Stream stream, 502 | object objectToWrite, 503 | Encoding encoding, 504 | int bufferSize, 505 | bool leaveOpen, 506 | bool resetStream, 507 | JsonSerializerSettings jsonSerializerSettings = default) 508 | { 509 | if (stream == null) 510 | { 511 | throw new ArgumentNullException(nameof(stream)); 512 | } 513 | 514 | if (!stream.CanWrite) 515 | { 516 | throw new NotSupportedException("Can't write to this stream."); 517 | } 518 | 519 | if (encoding == null) 520 | { 521 | throw new ArgumentNullException(nameof(encoding)); 522 | } 523 | 524 | using var streamWriter = new StreamWriter(stream, encoding, bufferSize, leaveOpen); 525 | 526 | using var jsonTextWriter = new JsonTextWriter(streamWriter); 527 | 528 | var jsonSerializer = jsonSerializerSettings == null ? JsonSerializer.Create() : JsonSerializer.Create(jsonSerializerSettings); 529 | jsonSerializer.Serialize(jsonTextWriter, objectToWrite); 530 | jsonTextWriter.Flush(); 531 | 532 | // after writing, set the stream to position 0 533 | if (resetStream && stream.CanSeek) 534 | { 535 | stream.Seek(0, SeekOrigin.Begin); 536 | } 537 | } 538 | } 539 | } 540 | -------------------------------------------------------------------------------- /src/Marvin.StreamExtensions/StreamExtensionsAsync.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using Newtonsoft.Json.Linq; 3 | using System; 4 | using System.IO; 5 | using System.Text; 6 | using System.Threading; 7 | using System.Threading.Tasks; 8 | 9 | namespace Marvin.StreamExtensions 10 | { 11 | /// 12 | /// Extensions for working with streams 13 | /// 14 | public static partial class StreamExtensions 15 | { 16 | /// 17 | /// Read from the stream and deserialize into an object of type T (assuming Json content). 18 | /// 19 | /// The object type 20 | /// The stream 21 | /// An object of type T 22 | public static async Task ReadAndDeserializeFromJsonAsync( 23 | this Stream stream) 24 | { 25 | return await ReadAndDeserializeFromJsonAsync(stream, new UTF8Encoding(), true, 26 | Defaults.DefaultBufferSizeOnRead, false); 27 | } 28 | 29 | /// 30 | /// Read from the stream and deserialize into an object of type T (assuming Json content). 31 | /// 32 | /// The object type 33 | /// The stream 34 | /// The encoding to use 35 | /// An object of type T 36 | public static async Task ReadAndDeserializeFromJsonAsync( 37 | this Stream stream, 38 | Encoding encoding) 39 | { 40 | return await ReadAndDeserializeFromJsonAsync(stream, encoding, true, 41 | Defaults.DefaultBufferSizeOnRead, false); 42 | } 43 | 44 | /// 45 | /// Read from the stream and deserialize into an object of type T (assuming Json content). 46 | /// 47 | /// The object type 48 | /// The stream 49 | /// True to detect encoding from byte order marks, false otherwise 50 | /// An object of type T 51 | public static async Task ReadAndDeserializeFromJsonAsync( 52 | this Stream stream, 53 | bool detectEncodingFromByteOrderMarks) 54 | { 55 | return await ReadAndDeserializeFromJsonAsync(stream, new UTF8Encoding(), 56 | detectEncodingFromByteOrderMarks, Defaults.DefaultBufferSizeOnRead, false); 57 | } 58 | 59 | /// 60 | /// Read from the stream and deserialize into an object of type T (assuming Json content). 61 | /// 62 | /// The object type 63 | /// The stream 64 | /// The encoding to use 65 | /// True to detect encoding from byte order marks, false otherwise 66 | /// The size of the buffer 67 | /// An object of type T 68 | public static async Task ReadAndDeserializeFromJsonAsync( 69 | this Stream stream, 70 | Encoding encoding, 71 | bool detectEncodingFromByteOrderMarks, 72 | int bufferSize) 73 | { 74 | return await ReadAndDeserializeFromJsonAsync(stream, encoding, 75 | detectEncodingFromByteOrderMarks, bufferSize, false); 76 | } 77 | 78 | /// 79 | /// Read from the stream and deserialize into an object of type T (assuming Json content). 80 | /// 81 | /// The object type 82 | /// The stream 83 | /// The encoding to use 84 | /// True to detect encoding from byte order marks, false otherwise 85 | /// The size of the buffer 86 | /// True to leave the stream open after the (internally used) StreamReader object is disposed 87 | /// An object of type T 88 | public static async Task ReadAndDeserializeFromJsonAsync( 89 | this Stream stream, 90 | Encoding encoding, 91 | bool detectEncodingFromByteOrderMarks, 92 | int bufferSize, 93 | bool leaveOpen) 94 | { 95 | if (stream == null) 96 | { 97 | throw new ArgumentNullException(nameof(stream)); 98 | } 99 | 100 | if (!stream.CanRead) 101 | { 102 | throw new NotSupportedException("Can't read from this stream."); 103 | } 104 | 105 | if (encoding == null) 106 | { 107 | throw new ArgumentNullException(nameof(encoding)); 108 | } 109 | 110 | using var streamReader = new StreamReader(stream, encoding, detectEncodingFromByteOrderMarks, bufferSize, leaveOpen); 111 | using var jsonTextReader = new JsonTextReader(streamReader); 112 | var jToken = await JToken.LoadAsync(jsonTextReader); 113 | return jToken.ToObject(); 114 | } 115 | 116 | /// 117 | /// Serialize (to Json) and write to the stream 118 | /// 119 | /// The type the object to serialize/write 120 | /// The stream 121 | /// The object to write to the stream 122 | /// The token to monitor for cancellation requests. The default value is System.Threading.CancellationToken.None. 123 | /// The JsonSerialization setting beeing used for serialization. In default state it will use default settings from Newtonsoft.Json.JsonConvert.DefaultSettings 124 | public static async Task SerializeToJsonAndWriteAsync( 125 | this Stream stream, 126 | T objectToWrite, 127 | CancellationToken cancellationToken = default, 128 | JsonSerializerSettings jsonSerializerSettings = default) 129 | { 130 | await SerializeToJsonAndWriteAsync(stream, objectToWrite, new UTF8Encoding(), Defaults.DefaultBufferSizeOnWrite, false, false, cancellationToken, jsonSerializerSettings); 131 | } 132 | 133 | /// 134 | /// Serialize (to Json) and write to the stream 135 | /// 136 | /// The type the object to serialize/write 137 | /// The stream 138 | /// The object to write to the stream 139 | /// The encoding to use 140 | /// The token to monitor for cancellation requests. The default value is System.Threading.CancellationToken.None. 141 | /// The JsonSerialization setting beeing used for serialization. In default state it will use default settings from Newtonsoft.Json.JsonConvert.DefaultSettings 142 | public static async Task SerializeToJsonAndWriteAsync( 143 | this Stream stream, 144 | T objectToWrite, 145 | Encoding encoding, 146 | CancellationToken cancellationToken = default, 147 | JsonSerializerSettings jsonSerializerSettings = default) 148 | { 149 | await SerializeToJsonAndWriteAsync(stream, objectToWrite, encoding, Defaults.DefaultBufferSizeOnWrite, false, false, cancellationToken, jsonSerializerSettings); 150 | } 151 | 152 | /// 153 | /// Serialize (to Json) and write to the stream 154 | /// 155 | /// The type the object to serialize/write 156 | /// The stream 157 | /// The object to write to the stream 158 | /// The encoding to use 159 | /// The size of the buffer 160 | /// The token to monitor for cancellation requests. The default value is System.Threading.CancellationToken.None. 161 | /// The JsonSerialization setting beeing used for serialization. In default state it will use default settings from Newtonsoft.Json.JsonConvert.DefaultSettings 162 | public static async Task SerializeToJsonAndWriteAsync( 163 | this Stream stream, 164 | T objectToWrite, 165 | Encoding encoding, 166 | int bufferSize, 167 | CancellationToken cancellationToken = default, 168 | JsonSerializerSettings jsonSerializerSettings = default) 169 | { 170 | await SerializeToJsonAndWriteAsync(stream, objectToWrite, encoding, bufferSize, false, false, cancellationToken, jsonSerializerSettings); 171 | } 172 | 173 | /// 174 | /// Serialize (to Json) and write to the stream 175 | /// 176 | /// The type the object to serialize/write 177 | /// The stream 178 | /// The object to write to the stream 179 | /// The encoding to use 180 | /// The size of the buffer 181 | /// True to leave the stream open after the (internally used) StreamWriter object is disposed 182 | /// The token to monitor for cancellation requests. The default value is System.Threading.CancellationToken.None. 183 | /// The JsonSerialization setting beeing used for serialization. In default state it will use default settings from Newtonsoft.Json.JsonConvert.DefaultSettings 184 | public static async Task SerializeToJsonAndWriteAsync( 185 | this Stream stream, 186 | T objectToWrite, 187 | Encoding encoding, 188 | int bufferSize, 189 | bool leaveOpen, 190 | CancellationToken cancellationToken = default, 191 | JsonSerializerSettings jsonSerializerSettings = default) 192 | { 193 | await SerializeToJsonAndWriteAsync(stream, objectToWrite, encoding, bufferSize, leaveOpen, false, cancellationToken, jsonSerializerSettings); 194 | } 195 | 196 | /// 197 | /// Serialize (to Json) and write to the stream 198 | /// 199 | /// The type the object to serialize/write 200 | /// The stream 201 | /// The object to write to the stream 202 | /// True to reset the stream to position 0 after writing, false otherwise 203 | /// The token to monitor for cancellation requests. The default value is System.Threading.CancellationToken.None. 204 | /// The JsonSerialization setting beeing used for serialization. In default state it will use default settings from Newtonsoft.Json.JsonConvert.DefaultSettings 205 | public static async Task SerializeToJsonAndWriteAsync( 206 | this Stream stream, 207 | T objectToWrite, 208 | bool resetStream, 209 | CancellationToken cancellationToken = default, 210 | JsonSerializerSettings jsonSerializerSettings = default) 211 | { 212 | await SerializeToJsonAndWriteAsync(stream, objectToWrite, new UTF8Encoding(), Defaults.DefaultBufferSizeOnWrite, false, resetStream, cancellationToken, jsonSerializerSettings); 213 | } 214 | 215 | /// 216 | /// Serialize (to Json) and write to the stream 217 | /// 218 | /// The type the object to serialize/write 219 | /// The stream 220 | /// The object to write to the stream 221 | /// The encoding to use 222 | /// True to reset the stream to position 0 after writing, false otherwise 223 | /// The token to monitor for cancellation requests. The default value is System.Threading.CancellationToken.None. 224 | /// The JsonSerialization setting beeing used for serialization. In default state it will use default settings from Newtonsoft.Json.JsonConvert.DefaultSettings 225 | public static async Task SerializeToJsonAndWriteAsync( 226 | this Stream stream, 227 | T objectToWrite, 228 | Encoding encoding, 229 | bool resetStream, 230 | CancellationToken cancellationToken = default, 231 | JsonSerializerSettings jsonSerializerSettings = default) 232 | { 233 | await SerializeToJsonAndWriteAsync(stream, objectToWrite, encoding, Defaults.DefaultBufferSizeOnWrite, false, resetStream, cancellationToken, jsonSerializerSettings); 234 | } 235 | 236 | /// 237 | /// Serialize (to Json) and write to the stream 238 | /// 239 | /// The type the object to serialize/write 240 | /// The stream 241 | /// The object to write to the stream 242 | /// The encoding to use 243 | /// The size of the buffer 244 | /// True to leave the stream open after the (internally used) StreamWriter object is disposed 245 | /// True to reset the stream to position 0 after writing, false otherwise 246 | /// The token to monitor for cancellation requests. The default value is System.Threading.CancellationToken.None. 247 | /// The JsonSerialization setting beeing used for serialization. In default state it will use default settings from Newtonsoft.Json.JsonConvert.DefaultSettings 248 | public static async Task SerializeToJsonAndWriteAsync( 249 | this Stream stream, 250 | T objectToWrite, 251 | Encoding encoding, 252 | int bufferSize, 253 | bool leaveOpen, 254 | bool resetStream, 255 | CancellationToken cancellationToken = default, 256 | JsonSerializerSettings jsonSerializerSettings = default) 257 | { 258 | if (stream == null) 259 | { 260 | throw new ArgumentNullException(nameof(stream)); 261 | } 262 | 263 | if (!stream.CanWrite) 264 | { 265 | throw new NotSupportedException("Can't write to this stream."); 266 | } 267 | 268 | if (encoding == null) 269 | { 270 | throw new ArgumentNullException(nameof(encoding)); 271 | } 272 | 273 | using var streamWriter = new StreamWriter(stream, encoding, bufferSize, leaveOpen); 274 | using var jsonTextWriter = new JsonTextWriter(streamWriter); 275 | var jsonSerializer = jsonSerializerSettings == default ? JsonSerializer.Create() : JsonSerializer.Create(jsonSerializerSettings); 276 | jsonSerializer.Serialize(jsonTextWriter, objectToWrite); 277 | await jsonTextWriter.FlushAsync(cancellationToken); 278 | 279 | 280 | // after writing, set the stream to position 0 281 | if (resetStream && stream.CanSeek) 282 | { 283 | stream.Seek(0, SeekOrigin.Begin); 284 | } 285 | } 286 | 287 | /// 288 | /// Serialize (to Json) and write to the stream 289 | /// 290 | /// The stream 291 | /// The object to write to the stream 292 | /// The token to monitor for cancellation requests. The default value is System.Threading.CancellationToken.None. 293 | /// The JsonSerialization setting beeing used for serialization. In default state it will use default settings from Newtonsoft.Json.JsonConvert.DefaultSettings 294 | public static async Task SerializeToJsonAndWriteAsync( 295 | this Stream stream, 296 | object objectToWrite, 297 | CancellationToken cancellationToken = default, 298 | JsonSerializerSettings jsonSerializerSettings = default) 299 | { 300 | await SerializeToJsonAndWriteAsync(stream, objectToWrite, new UTF8Encoding(), Defaults.DefaultBufferSizeOnWrite, false, false, cancellationToken, jsonSerializerSettings); 301 | } 302 | 303 | /// 304 | /// Serialize (to Json) and write to the stream 305 | /// 306 | /// The stream 307 | /// The object to write to the stream 308 | /// The encoding to use 309 | /// The token to monitor for cancellation requests. The default value is System.Threading.CancellationToken.None. 310 | /// The JsonSerialization setting beeing used for serialization. In default state it will use default settings from Newtonsoft.Json.JsonConvert.DefaultSettings 311 | public static async Task SerializeToJsonAndWriteAsync( 312 | this Stream stream, 313 | object objectToWrite, 314 | Encoding encoding, 315 | CancellationToken cancellationToken = default, 316 | JsonSerializerSettings jsonSerializerSettings = default) 317 | { 318 | await SerializeToJsonAndWriteAsync(stream, objectToWrite, encoding, Defaults.DefaultBufferSizeOnWrite, false, false, cancellationToken, jsonSerializerSettings); 319 | } 320 | 321 | /// 322 | /// Serialize (to Json) and write to the stream 323 | /// 324 | /// The stream 325 | /// The object to write to the stream 326 | /// The encoding to use 327 | /// The size of the buffer 328 | /// The token to monitor for cancellation requests. The default value is System.Threading.CancellationToken.None. 329 | /// The JsonSerialization setting beeing used for serialization. In default state it will use default settings from Newtonsoft.Json.JsonConvert.DefaultSettings 330 | public static async Task SerializeToJsonAndWriteAsync( 331 | this Stream stream, 332 | object objectToWrite, 333 | Encoding encoding, 334 | int bufferSize, 335 | CancellationToken cancellationToken = default, 336 | JsonSerializerSettings jsonSerializerSettings = default) 337 | { 338 | await SerializeToJsonAndWriteAsync(stream, objectToWrite, encoding, bufferSize, false, false, cancellationToken, jsonSerializerSettings); 339 | } 340 | 341 | /// 342 | /// Serialize (to Json) and write to the stream 343 | /// 344 | /// The stream 345 | /// The object to write to the stream 346 | /// The encoding to use 347 | /// The size of the buffer 348 | /// True to leave the stream open after the (internally used) StreamWriter object is disposed 349 | /// The token to monitor for cancellation requests. The default value is System.Threading.CancellationToken.None. 350 | /// The JsonSerialization setting beeing used for serialization. In default state it will use default settings from Newtonsoft.Json.JsonConvert.DefaultSettings 351 | public static async Task SerializeToJsonAndWriteAsync( 352 | this Stream stream, 353 | object objectToWrite, 354 | Encoding encoding, 355 | int bufferSize, 356 | bool leaveOpen, 357 | CancellationToken cancellationToken = default, 358 | JsonSerializerSettings jsonSerializerSettings = default) 359 | { 360 | await SerializeToJsonAndWriteAsync(stream, objectToWrite, encoding, bufferSize, leaveOpen, false, cancellationToken, jsonSerializerSettings); 361 | } 362 | 363 | /// 364 | /// Serialize (to Json) and write to the stream 365 | /// 366 | /// The stream 367 | /// The object to write to the stream 368 | /// True to reset the stream to position 0 after writing, false otherwise 369 | /// The token to monitor for cancellation requests. The default value is System.Threading.CancellationToken.None. 370 | /// The JsonSerialization setting beeing used for serialization. In default state it will use default settings from Newtonsoft.Json.JsonConvert.DefaultSettings 371 | public static async Task SerializeToJsonAndWriteAsync( 372 | this Stream stream, 373 | object objectToWrite, 374 | bool resetStream, 375 | CancellationToken cancellationToken = default, 376 | JsonSerializerSettings jsonSerializerSettings = default) 377 | { 378 | await SerializeToJsonAndWriteAsync(stream, objectToWrite, new UTF8Encoding(), Defaults.DefaultBufferSizeOnWrite, false, resetStream, cancellationToken, jsonSerializerSettings); 379 | } 380 | 381 | /// 382 | /// Serialize (to Json) and write to the stream 383 | /// 384 | /// The stream 385 | /// The object to write to the stream 386 | /// The encoding to use 387 | /// True to reset the stream to position 0 after writing, false otherwise 388 | /// The token to monitor for cancellation requests. The default value is System.Threading.CancellationToken.None. 389 | /// The JsonSerialization setting beeing used for serialization. In default state it will use default settings from Newtonsoft.Json.JsonConvert.DefaultSettings 390 | public static async Task SerializeToJsonAndWriteAsync( 391 | this Stream stream, 392 | object objectToWrite, 393 | Encoding encoding, 394 | bool resetStream, 395 | CancellationToken cancellationToken = default, 396 | JsonSerializerSettings jsonSerializerSettings = default) 397 | { 398 | await SerializeToJsonAndWriteAsync(stream, objectToWrite, encoding, Defaults.DefaultBufferSizeOnWrite, false, resetStream, cancellationToken, jsonSerializerSettings); 399 | } 400 | 401 | /// 402 | /// Serialize (to Json) and write to the stream 403 | /// 404 | /// The stream 405 | /// The object to write to the stream 406 | /// The encoding to use 407 | /// The size of the buffer 408 | /// True to leave the stream open after the (internally used) StreamWriter object is disposed 409 | /// True to reset the stream to position 0 after writing, false otherwise 410 | /// The token to monitor for cancellation requests. The default value is System.Threading.CancellationToken.None. 411 | /// The JsonSerialization setting beeing used for serialization. In default state it will use default settings from Newtonsoft.Json.JsonConvert.DefaultSettings 412 | public static async Task SerializeToJsonAndWriteAsync( 413 | this Stream stream, 414 | object objectToWrite, 415 | Encoding encoding, 416 | int bufferSize, 417 | bool leaveOpen, 418 | bool resetStream, 419 | CancellationToken cancellationToken = default, 420 | JsonSerializerSettings jsonSerializerSettings = default) 421 | { 422 | if (stream == null) 423 | { 424 | throw new ArgumentNullException(nameof(stream)); 425 | } 426 | 427 | if (!stream.CanWrite) 428 | { 429 | throw new NotSupportedException("Can't write to this stream."); 430 | } 431 | 432 | if (encoding == null) 433 | { 434 | throw new ArgumentNullException(nameof(encoding)); 435 | } 436 | 437 | using var streamWriter = new StreamWriter(stream, encoding, bufferSize, leaveOpen); 438 | using var jsonTextWriter = new JsonTextWriter(streamWriter); 439 | var jsonSerializer = jsonSerializerSettings == default ? JsonSerializer.Create() : JsonSerializer.Create(jsonSerializerSettings); 440 | jsonSerializer.Serialize(jsonTextWriter, objectToWrite); 441 | await jsonTextWriter.FlushAsync(cancellationToken); 442 | 443 | // after writing, set the stream to position 0 444 | if (resetStream && stream.CanSeek) 445 | { 446 | stream.Seek(0, SeekOrigin.Begin); 447 | } 448 | } 449 | } 450 | } 451 | -------------------------------------------------------------------------------- /test/Marvin.StreamExtensions.Test/Marvin.StreamExtensions.Test.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp2.1 5 | 6 | false 7 | 8 | 9 | 10 | latest 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /test/Marvin.StreamExtensions.Test/Person.cs: -------------------------------------------------------------------------------- 1 | namespace Marvin.StreamExtensions.Test 2 | { 3 | public class Person 4 | { 5 | public string Name { get; set; } 6 | 7 | public override bool Equals(object obj) 8 | { 9 | var input = (Person)obj; 10 | return input.Name == Name; 11 | } 12 | 13 | // generate hashcode 14 | public override int GetHashCode() 15 | { 16 | return !string.IsNullOrEmpty(Name) 17 | ? Name.GetHashCode() 18 | : 0; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /test/Marvin.StreamExtensions.Test/ResponseMessageTests.cs: -------------------------------------------------------------------------------- 1 | using System.Net; 2 | using System.Net.Http; 3 | using System.Net.Http.Headers; 4 | using System.Text; 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | using Moq; 8 | using Moq.Protected; 9 | using Newtonsoft.Json; 10 | using Newtonsoft.Json.Linq; 11 | using Xunit; 12 | 13 | namespace Marvin.StreamExtensions.Test 14 | { 15 | public class ResponseMessageTests 16 | { 17 | [Fact] 18 | public async Task DeserializeTypedResponse_MustMatchInput() 19 | { 20 | var person = new Person { Name = "Lord Flashheart" }; 21 | Person personAfterResponse; 22 | 23 | // create mocked HttpMessageHandler 24 | var bounceInputHttpMessageHandlerMock = new Mock(); 25 | 26 | // set up the method 27 | bounceInputHttpMessageHandlerMock 28 | .Protected() 29 | .Setup>( 30 | "SendAsync", 31 | ItExpr.IsAny(), 32 | ItExpr.IsAny() 33 | ) 34 | .ReturnsAsync(new HttpResponseMessage() 35 | { 36 | StatusCode = HttpStatusCode.OK, 37 | Content = new StringContent(JsonConvert.SerializeObject(person)) 38 | }); 39 | 40 | // instantiate client 41 | var httpClient = new HttpClient(bounceInputHttpMessageHandlerMock.Object); 42 | 43 | // send some json 44 | var request = new HttpRequestMessage(HttpMethod.Post, "http://api/test") 45 | { 46 | Content = new StringContent(JsonConvert.SerializeObject(person)) 47 | }; 48 | request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); 49 | 50 | using (var response = await httpClient.SendAsync(request)) 51 | { 52 | personAfterResponse = await response.DeserializeAsStreamAsync(new UTF8Encoding(), false, 1024, true); 53 | } 54 | 55 | Assert.Equal(person, personAfterResponse); 56 | } 57 | 58 | [Fact] 59 | public async Task DeserializeResponse_MustMatchInput() 60 | { 61 | var person = new Person { Name = "Lord Flashheart" }; 62 | Person personAfterResponse; 63 | 64 | // create mocked HttpMessageHandler 65 | var bounceInputHttpMessageHandlerMock = new Mock(); 66 | 67 | // set up the method 68 | bounceInputHttpMessageHandlerMock 69 | .Protected() 70 | .Setup>( 71 | "SendAsync", 72 | ItExpr.IsAny(), 73 | ItExpr.IsAny() 74 | ) 75 | .ReturnsAsync(new HttpResponseMessage() 76 | { 77 | StatusCode = HttpStatusCode.OK, 78 | Content = new StringContent(JsonConvert.SerializeObject(person)) 79 | }); 80 | 81 | // instantiate client 82 | var httpClient = new HttpClient(bounceInputHttpMessageHandlerMock.Object); 83 | 84 | // send some json 85 | var request = new HttpRequestMessage(HttpMethod.Post, "http://api/test") 86 | { 87 | Content = new StringContent(JsonConvert.SerializeObject(person)) 88 | }; 89 | request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); 90 | 91 | using (var response = await httpClient.SendAsync(request)) 92 | { 93 | var output = await response.DeserializeAsStreamAsync(new UTF8Encoding(), false, 1024, true); 94 | // cast - just testing the non-typed ReadAndDeserializeFromJson method 95 | personAfterResponse = ((JObject)output).ToObject(); 96 | } 97 | Assert.Equal(person, personAfterResponse); 98 | } 99 | } 100 | } -------------------------------------------------------------------------------- /test/Marvin.StreamExtensions.Test/StreamTests.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Net; 3 | using System.Net.Http; 4 | using System.Net.Http.Headers; 5 | using System.Text; 6 | using System.Threading; 7 | using System.Threading.Tasks; 8 | using Moq; 9 | using Moq.Protected; 10 | using Newtonsoft.Json; 11 | using Newtonsoft.Json.Linq; 12 | using Xunit; 13 | 14 | namespace Marvin.StreamExtensions.Test 15 | { 16 | public class StreamTests 17 | { 18 | [Fact] 19 | public async Task SerializeInputToStream_MustMatchInput() 20 | { 21 | var person = new Person() { Name = "Lord Flashheart" }; 22 | Person personAfterResponse; 23 | 24 | // create mocked HttpMessageHandler 25 | var bounceInputHttpMessageHandlerMock = new Mock(); 26 | 27 | // set up the method 28 | bounceInputHttpMessageHandlerMock 29 | .Protected() 30 | .Setup>( 31 | "SendAsync", 32 | ItExpr.IsAny(), 33 | ItExpr.IsAny() 34 | ) 35 | .ReturnsAsync(new HttpResponseMessage() 36 | { 37 | StatusCode = HttpStatusCode.OK, 38 | Content = new StringContent(JsonConvert.SerializeObject(person)) 39 | }); 40 | 41 | // instantiate client 42 | var httpClient = new HttpClient(bounceInputHttpMessageHandlerMock.Object); 43 | 44 | var memoryContentStream = new MemoryStream(); 45 | memoryContentStream.SerializeToJsonAndWrite(person, new UTF8Encoding(), 1024, true, true); 46 | 47 | using (var request = new HttpRequestMessage( 48 | HttpMethod.Post, 49 | "http://api/test")) 50 | { 51 | request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); 52 | using (var streamContent = new StreamContent(memoryContentStream)) 53 | { 54 | streamContent.Headers.ContentType = new MediaTypeHeaderValue("application/json"); 55 | request.Content = streamContent; 56 | 57 | using (var response = await httpClient.SendAsync(request)) 58 | { 59 | _ = await response.Content.ReadAsStreamAsync(); 60 | 61 | response.EnsureSuccessStatusCode(); 62 | personAfterResponse = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync()); 63 | } 64 | } 65 | } 66 | 67 | Assert.Equal(person, personAfterResponse); 68 | } 69 | 70 | [Fact] 71 | public async Task SerializeInputToStream_Async_MustMatchInput() 72 | { 73 | var person = new Person() { Name = "Lord Flashheart" }; 74 | Person personAfterResponse; 75 | 76 | // create mocked HttpMessageHandler 77 | var bounceInputHttpMessageHandlerMock = new Mock(); 78 | 79 | // set up the method 80 | bounceInputHttpMessageHandlerMock 81 | .Protected() 82 | .Setup>( 83 | "SendAsync", 84 | ItExpr.IsAny(), 85 | ItExpr.IsAny() 86 | ) 87 | .ReturnsAsync(new HttpResponseMessage() 88 | { 89 | StatusCode = HttpStatusCode.OK, 90 | Content = new StringContent(JsonConvert.SerializeObject(person)) 91 | }); 92 | 93 | // instantiate client 94 | var httpClient = new HttpClient(bounceInputHttpMessageHandlerMock.Object); 95 | 96 | var memoryContentStream = new MemoryStream(); 97 | await memoryContentStream.SerializeToJsonAndWriteAsync(person, new UTF8Encoding(), 1024, false, true); 98 | 99 | using (var request = new HttpRequestMessage( 100 | HttpMethod.Post, 101 | "http://api/test")) 102 | { 103 | request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); 104 | using (var streamContent = new StreamContent(memoryContentStream)) 105 | { 106 | streamContent.Headers.ContentType = new MediaTypeHeaderValue("application/json"); 107 | request.Content = streamContent; 108 | 109 | using (var response = await httpClient.SendAsync(request)) 110 | { 111 | _ = await response.Content.ReadAsStreamAsync(); 112 | 113 | response.EnsureSuccessStatusCode(); 114 | personAfterResponse = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync()); 115 | } 116 | } 117 | } 118 | Assert.Equal(person, personAfterResponse); 119 | } 120 | 121 | [Fact] 122 | public async Task SerializeTypedInputToStream_MustMatchInput() 123 | { 124 | var person = new Person() { Name = "Lord Flashheart" }; 125 | Person personAfterResponse; 126 | 127 | // create mocked HttpMessageHandler 128 | var bounceInputHttpMessageHandlerMock = new Mock(); 129 | 130 | // set up the method 131 | bounceInputHttpMessageHandlerMock 132 | .Protected() 133 | .Setup>( 134 | "SendAsync", 135 | ItExpr.IsAny(), 136 | ItExpr.IsAny() 137 | ) 138 | .ReturnsAsync(new HttpResponseMessage() 139 | { 140 | StatusCode = HttpStatusCode.OK, 141 | Content = new StringContent(JsonConvert.SerializeObject(person)) 142 | }); 143 | 144 | // instantiate client 145 | var httpClient = new HttpClient(bounceInputHttpMessageHandlerMock.Object); 146 | 147 | var memoryContentStream = new MemoryStream(); 148 | memoryContentStream.SerializeToJsonAndWrite(person, new UTF8Encoding(), 1024, true, true); 149 | 150 | using (var request = new HttpRequestMessage( 151 | HttpMethod.Post, 152 | "http://api/test")) 153 | { 154 | request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); 155 | using (var streamContent = new StreamContent(memoryContentStream)) 156 | { 157 | streamContent.Headers.ContentType = new MediaTypeHeaderValue("application/json"); 158 | request.Content = streamContent; 159 | 160 | using (var response = await httpClient.SendAsync(request)) 161 | { 162 | _ = await response.Content.ReadAsStreamAsync(); 163 | 164 | response.EnsureSuccessStatusCode(); 165 | personAfterResponse = JsonConvert.DeserializeObject( 166 | await response.Content.ReadAsStringAsync()); 167 | } 168 | } 169 | } 170 | Assert.Equal(person, personAfterResponse); 171 | } 172 | 173 | [Fact] 174 | public async Task SerializeTypedInputToStream_Async_MustMatchInput() 175 | { 176 | var person = new Person() { Name = "Lord Flashheart" }; 177 | Person personAfterResponse; 178 | 179 | // create mocked HttpMessageHandler 180 | var bounceInputHttpMessageHandlerMock = new Mock(); 181 | 182 | // set up the method 183 | bounceInputHttpMessageHandlerMock 184 | .Protected() 185 | .Setup>( 186 | "SendAsync", 187 | ItExpr.IsAny(), 188 | ItExpr.IsAny() 189 | ) 190 | .ReturnsAsync(new HttpResponseMessage() 191 | { 192 | StatusCode = HttpStatusCode.OK, 193 | Content = new StringContent(JsonConvert.SerializeObject(person)) 194 | }); 195 | 196 | // instantiate client 197 | var httpClient = new HttpClient(bounceInputHttpMessageHandlerMock.Object); 198 | 199 | var memoryContentStream = new MemoryStream(); 200 | await memoryContentStream.SerializeToJsonAndWriteAsync(person, new UTF8Encoding(), 1024, true, true); 201 | 202 | using (var request = new HttpRequestMessage( 203 | HttpMethod.Post, 204 | "http://api/test")) 205 | { 206 | request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); 207 | using (var streamContent = new StreamContent(memoryContentStream)) 208 | { 209 | streamContent.Headers.ContentType = new MediaTypeHeaderValue("application/json"); 210 | request.Content = streamContent; 211 | 212 | using (var response = await httpClient.SendAsync(request)) 213 | { 214 | _ = await response.Content.ReadAsStreamAsync(); 215 | 216 | response.EnsureSuccessStatusCode(); 217 | personAfterResponse = JsonConvert.DeserializeObject( 218 | await response.Content.ReadAsStringAsync()); 219 | } 220 | } 221 | } 222 | Assert.Equal(person, personAfterResponse); 223 | } 224 | 225 | 226 | [Fact] 227 | public async Task DeserializeTypedResponseFromStream_MustMatchInput() 228 | { 229 | var person = new Person() { Name = "Lord Flashheart" }; 230 | Person personAfterResponse; 231 | 232 | // create mocked HttpMessageHandler 233 | var bounceInputHttpMessageHandlerMock = new Mock(); 234 | 235 | // set up the method 236 | bounceInputHttpMessageHandlerMock 237 | .Protected() 238 | .Setup>( 239 | "SendAsync", 240 | ItExpr.IsAny(), 241 | ItExpr.IsAny() 242 | ) 243 | .ReturnsAsync(new HttpResponseMessage() 244 | { 245 | StatusCode = HttpStatusCode.OK, 246 | Content = new StringContent(JsonConvert.SerializeObject(person)) 247 | }); 248 | 249 | // instantiate client 250 | var httpClient = new HttpClient(bounceInputHttpMessageHandlerMock.Object); 251 | 252 | // send some json 253 | var request = new HttpRequestMessage(HttpMethod.Post, "http://api/test") 254 | { 255 | Content = new StringContent(JsonConvert.SerializeObject(person)) 256 | }; 257 | request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); 258 | 259 | using (var response = await httpClient.SendAsync(request)) 260 | { 261 | var stream = await response.Content.ReadAsStreamAsync(); 262 | personAfterResponse = stream.ReadAndDeserializeFromJson(new UTF8Encoding(), false, 1024, true); 263 | } 264 | 265 | Assert.Equal(person, personAfterResponse); 266 | } 267 | 268 | [Fact] 269 | public async Task DeserializeTypedResponseFromStream_Async_MustMatchInput() 270 | { 271 | var person = new Person() { Name = "Lord Flashheart" }; 272 | Person personAfterResponse; 273 | 274 | // create mocked HttpMessageHandler 275 | var bounceInputHttpMessageHandlerMock = new Mock(); 276 | 277 | // set up the method 278 | bounceInputHttpMessageHandlerMock 279 | .Protected() 280 | .Setup>( 281 | "SendAsync", 282 | ItExpr.IsAny(), 283 | ItExpr.IsAny() 284 | ) 285 | .ReturnsAsync(new HttpResponseMessage() 286 | { 287 | StatusCode = HttpStatusCode.OK, 288 | Content = new StringContent(JsonConvert.SerializeObject(person)) 289 | }); 290 | 291 | // instantiate client 292 | var httpClient = new HttpClient(bounceInputHttpMessageHandlerMock.Object); 293 | 294 | // send some json 295 | var request = new HttpRequestMessage(HttpMethod.Post, "http://api/test") 296 | { 297 | Content = new StringContent(JsonConvert.SerializeObject(person)) 298 | }; 299 | request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); 300 | 301 | using (var response = await httpClient.SendAsync(request)) 302 | { 303 | var stream = await response.Content.ReadAsStreamAsync(); 304 | 305 | personAfterResponse = await stream.ReadAndDeserializeFromJsonAsync(new UTF8Encoding(), false, 1024, true); 306 | } 307 | 308 | Assert.Equal(person, personAfterResponse); 309 | } 310 | 311 | [Fact] 312 | public async Task DeserializeResponseFromStream_MustMatchInput() 313 | { 314 | var person = new Person() { Name = "Lord Flashheart" }; 315 | Person personAfterResponse; 316 | 317 | // create mocked HttpMessageHandler 318 | var bounceInputHttpMessageHandlerMock = new Mock(); 319 | 320 | // set up the method 321 | bounceInputHttpMessageHandlerMock 322 | .Protected() 323 | .Setup>( 324 | "SendAsync", 325 | ItExpr.IsAny(), 326 | ItExpr.IsAny() 327 | ) 328 | .ReturnsAsync(new HttpResponseMessage() 329 | { 330 | StatusCode = HttpStatusCode.OK, 331 | Content = new StringContent(JsonConvert.SerializeObject(person)) 332 | }); 333 | 334 | // instantiate client 335 | var httpClient = new HttpClient(bounceInputHttpMessageHandlerMock.Object); 336 | 337 | // send some json 338 | var request = new HttpRequestMessage(HttpMethod.Post, "http://api/test") 339 | { 340 | Content = new StringContent(JsonConvert.SerializeObject(person)) 341 | }; 342 | request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); 343 | 344 | using (var response = await httpClient.SendAsync(request)) 345 | { 346 | var stream = await response.Content.ReadAsStreamAsync(); 347 | var output = stream.ReadAndDeserializeFromJson(new UTF8Encoding(), false, 1024, true); 348 | // cast - just testing the non-typed ReadAndDeserializeFromJson method 349 | personAfterResponse = ((JObject)output).ToObject(); 350 | } 351 | Assert.Equal(person, personAfterResponse); 352 | } 353 | 354 | [Fact] 355 | public async Task DeserializeResponseFromStream_Async_MustMatchInput() 356 | { 357 | var person = new Person() { Name = "Lord Flashheart" }; 358 | Person personAfterResponse; 359 | 360 | // create mocked HttpMessageHandler 361 | var bounceInputHttpMessageHandlerMock = new Mock(); 362 | 363 | // set up the method 364 | bounceInputHttpMessageHandlerMock 365 | .Protected() 366 | .Setup>( 367 | "SendAsync", 368 | ItExpr.IsAny(), 369 | ItExpr.IsAny() 370 | ) 371 | .ReturnsAsync(new HttpResponseMessage() 372 | { 373 | StatusCode = HttpStatusCode.OK, 374 | Content = new StringContent(JsonConvert.SerializeObject(person)) 375 | }); 376 | 377 | // instantiate client 378 | var httpClient = new HttpClient(bounceInputHttpMessageHandlerMock.Object); 379 | 380 | // send some json 381 | var request = new HttpRequestMessage(HttpMethod.Post, "http://api/test") 382 | { 383 | Content = new StringContent(JsonConvert.SerializeObject(person)) 384 | }; 385 | request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); 386 | 387 | using (var response = await httpClient.SendAsync(request)) 388 | { 389 | var stream = await response.Content.ReadAsStreamAsync(); 390 | var output = await stream.ReadAndDeserializeFromJsonAsync(new UTF8Encoding(), false, 1024, true); 391 | // cast - just testing the non-typed ReadAndDeserializeFromJson method 392 | personAfterResponse = ((JObject)output).ToObject(); 393 | } 394 | Assert.Equal(person, personAfterResponse); 395 | } 396 | 397 | [Fact] 398 | public async Task SerializeTypedInputToStream_Async_CanceledThrowsTaskCanceledException() 399 | { 400 | var person = new Person(); 401 | var cancellationTokenSource = new CancellationTokenSource(); 402 | cancellationTokenSource.Cancel(); 403 | 404 | using (var memoryStream = new MemoryStream()) 405 | { 406 | await Assert.ThrowsAsync(async () => 407 | // test simple overload to also ensure the more complex overload is passed the token 408 | await memoryStream.SerializeToJsonAndWriteAsync(person, cancellationTokenSource.Token) 409 | ); 410 | } 411 | } 412 | } 413 | } 414 | --------------------------------------------------------------------------------