OnWriteToStreamAsync takes a Stream. If you create a StreamWriter from it, and close the StreamWriter, that will close the StreamWriter
and the underlying stream. Is this ok? Should or should not a media type formatter close the stream that is passed to it?
You should NOT close the stream in the WriteToStreamAync method using StreamWriter just for the same reason as you mentioned.
Web API disposes the HttpResponseMessage at the lower layers which will dispose off the stream too.
BTW, since MediaTypeFormatters can be used both on Client and Server side, it would interesting to see how the Stream disposing thing works at the Client. I can imagine that we could dispose off the HttpRequestMessage to dispose the content it is holding,
but I am currently not sure...will let you know soon.
[UPDATE]
On the Client side, HttpClient disposes the Request content, but for HttpResponseMessage, you would need to dispose it yourself.
Another question though... if we look at Daniel Roth's
VCard example we see the following method, called (potentially) from a loop:-
private void WriteContact(Contact contact, Stream stream)
{
var writer = new StreamWriter(stream);
writer.WriteLine("BEGIN:VCARD");
// [snip]
writer.WriteLine("END:VCARD");
writer.Flush();
}
After the method finishes, the 'writer' local variable is out of scope and subject to finalization. What if finalization were to occur? Would it not close the stream?
Yeah, the 'writer' variable would be out of scope, but I don't think it will be subjected to finalization immediately. The finalization happnes when the GC process kicks in and which is non-deterministic. During this GC phase when the finalization happens,
i expect the stream to be also closed.
Yeah, the 'writer' variable would be out of scope, but I don't think it will be subjected to finalization immediately. The finalization happnes when the GC process kicks in and which is non-deterministic. During this GC phase when the finalization happens,
i expect the stream to be also closed.
I think this is a problem, Kiran. As you say, when the GC process kicks in is non-deterministic. Ergo it
could kick in and close the framework-supplied stream before the framework wants it to be closed.
I think this is an issue. It's not "a bug", but it's certainly a gotcha. What would be the team's guidance here? I'm not seeing any defense against this in example code from Microsoft. Can I log this as an issue somewhere?
As you say, when the GC process kicks in is non-deterministic. Ergo it could kick in and close the framework-supplied stream before the framework wants it to be closed.
In practical terms, the problem of GC kicking in and a finalizer closing the response stream prematurely wasn't a problem in WCF Web API, because the actual type of Stream at runtime was something that didn't do anything when the Flush() or Close() methods
were called (I looked at the source). I.e. it was all in-memory.
It will be interesting to look at the source code for System.Web.HttpResponseStream, which is used for ASP.NET Web API.
awebb
Member
204 Points
91 Posts
Media type formatters - should they close the stream?
Feb 27, 2012 04:18 PM|LINK
OnWriteToStreamAsync takes a Stream. If you create a StreamWriter from it, and close the StreamWriter, that will close the StreamWriter and the underlying stream. Is this ok? Should or should not a media type formatter close the stream that is passed to it?
Kiran Challa
Participant
1442 Points
281 Posts
Microsoft
Re: Media type formatters - should they close the stream?
Feb 27, 2012 04:25 PM|LINK
You should NOT close the stream in the WriteToStreamAync method using StreamWriter just for the same reason as you mentioned.
Web API disposes the HttpResponseMessage at the lower layers which will dispose off the stream too.
BTW, since MediaTypeFormatters can be used both on Client and Server side, it would interesting to see how the Stream disposing thing works at the Client. I can imagine that we could dispose off the HttpRequestMessage to dispose the content it is holding, but I am currently not sure...will let you know soon.
[UPDATE]
On the Client side, HttpClient disposes the Request content, but for HttpResponseMessage, you would need to dispose it yourself.
Kiran Challa
awebb
Member
204 Points
91 Posts
Re: Media type formatters - should they close the stream?
Feb 28, 2012 06:08 AM|LINK
Kiran, thanks for a definitive answer!
Another question though... if we look at Daniel Roth's VCard example we see the following method, called (potentially) from a loop:-
private void WriteContact(Contact contact, Stream stream) { var writer = new StreamWriter(stream); writer.WriteLine("BEGIN:VCARD"); // [snip] writer.WriteLine("END:VCARD"); writer.Flush(); }After the method finishes, the 'writer' local variable is out of scope and subject to finalization. What if finalization were to occur? Would it not close the stream?
Kiran Challa
Participant
1442 Points
281 Posts
Microsoft
Re: Media type formatters - should they close the stream?
Feb 28, 2012 03:31 PM|LINK
Yeah, the 'writer' variable would be out of scope, but I don't think it will be subjected to finalization immediately. The finalization happnes when the GC process kicks in and which is non-deterministic. During this GC phase when the finalization happens, i expect the stream to be also closed.
Kiran Challa
awebb
Member
204 Points
91 Posts
Re: Media type formatters - should they close the stream?
Feb 28, 2012 03:39 PM|LINK
I think this is a problem, Kiran. As you say, when the GC process kicks in is non-deterministic. Ergo it could kick in and close the framework-supplied stream before the framework wants it to be closed.
I think this is an issue. It's not "a bug", but it's certainly a gotcha. What would be the team's guidance here? I'm not seeing any defense against this in example code from Microsoft. Can I log this as an issue somewhere?
awebb
Member
204 Points
91 Posts
Re: Media type formatters - should they close the stream?
Feb 29, 2012 07:43 AM|LINK
In practical terms, the problem of GC kicking in and a finalizer closing the response stream prematurely wasn't a problem in WCF Web API, because the actual type of Stream at runtime was something that didn't do anything when the Flush() or Close() methods were called (I looked at the source). I.e. it was all in-memory.
It will be interesting to look at the source code for System.Web.HttpResponseStream, which is used for ASP.NET Web API.