Writing an HttpContent extension that parses json using Rx
-
Samstag, 5. Mai 2012 04:15
I'm currently writing an extension method that deserializes a stream from json to an object using json.net and would like to know if i'm using the proper way to ensure that the streams and readers are properly disposed.
My current implementation code is below:
public static Task<T> ReadFromJsonAsAsync<T>(this HttpContent content) { return content .ReadAsStreamAsync() .ToObservable() .SelectMany(x => Observable.Using(() => x, s => Observable.Return(s))) .SelectMany(x => Observable.Using(() => new StreamReader(x), r => Observable.Return(r))) .SelectMany(x => Observable.Using(() => new JsonTextReader(x), r => Observable.Return(r))) .Select(x => { var js = new JsonSerializer(); js.Converters.Add(new IsoDateTimeConverter()); return js.Deserialize<T>(x); }) .ToTask(); }
Alle Antworten
-
Samstag, 5. Mai 2012 12:40
Hi,
If you're starting from task and ending in task, why not just use async/await?
public static async Task<T> ReadFromJsonAsAsync<T>(this HttpContent content) { var stream = await content.ReadAsStreamAsync(); using (stream) using (var reader = new StreamReader(stream)) using (var jsonReader = new JsonTextReader(reader)) { var js = new JsonSerializer(); js.Converters.Add(new IsoDateTimeConverter()); return js.Deserialize<T>(jsonReader); } }Though if you must use Rx, then the equivalent would be this:
return content .ReadAsStreamAsync() .ToObservable() .SelectMany(stream => Observable.Using(() => stream, s => Observable.Using(() => new StreamReader(s), reader => Observable.Using(() => new JsonTextReader(reader), jsonReader => { var js = new JsonSerializer(); js.Converters.Add(new IsoDateTimeConverter()); return Observable.Return(js.Deserialize<T>(jsonReader)); })))) .ToTask();- Dave
- Bearbeitet Dave Sexton Samstag, 5. Mai 2012 12:41 Small bug fix
-
Samstag, 5. Mai 2012 12:48
Hi,
Since your query does only synchronous work after the inital call, here's a simpler way to achieve the same results in Rx, though I'd still recommend using async/await instead.
return content .ReadAsStreamAsync() .ToObservable() .Select(stream => { using (stream) using (var reader = new StreamReader(stream)) using (var jsonReader = new JsonTextReader(reader)) { var js = new JsonSerializer(); js.Converters.Add(new IsoDateTimeConverter()); return js.Deserialize<T>(jsonReader); } }) .ToTask();- Dave
-
Samstag, 5. Mai 2012 17:59
I'd like to be able to use async and await but the only problem is that this code needs to be hosted in azure which means the code needs to target .net 4 and needs to build using vs10 for package deployment. Currently, there is no tooling support in vs11 for azure deployment and if vs10 sees the code it will blow up. Also, the async ctp won't install properly on Windows 8.
I'd love to hear if you've managed to deploy vs11 async code to azure. That combined with the async and await integration with rx 2.0 would make a number of our Task based interop points with Rx easier as we could await observables directly.
The reason why I'm starting and ending with Task is to maintain the signature with the other ReadAs extension methods off HttpContent. I do like your simpler approach of using select with using statements after the async network request returns.
-
Sonntag, 6. Mai 2012 17:53
Hi,
> I'd love to hear if you've managed to deploy vs11 async code to azure
I haven't tried. I've got very little experience with Azure, sorry.
- Dave
-
Mittwoch, 9. Mai 2012 14:28This post might help you deploy .NET 4.5 to Azure: http://www.magnusmartensson.com/post/2012/04/02/howto_put_net45_beta_and_aspnetmvc4_beta_on_windowsazure.aspx
Ryan Riley

