I have multiple Attribute classes which need to access the data in an HttpContent
(which is in an HttpActionContext
's HttpRequstMessage
) but I am having issues deciding on the best way to do it. I considered using the ReadAsStringAsync
method on the HttpContent
, but it seems that I need access to the Stream
to first set the position to 0.
The naive way seems to just wrap a StreamReader
around the base stream with a using
statement like so:
public override void OnActionExecuting(HttpActionContext actionContext)
{
string rawJson;
using (StreamReader streamReader = new StreamReader(actionContext.Request.Content.ReadAsStreamAsync().Result))
{
streamReader.BaseStream.Position = 0;
rawJson = streamReader.ReadToEnd();
}
// etc
}
This works well for the first attribute that executes but every subsequent attribute that executes throws an exception on actionContext.Request.Content.ReadAsStreamAsync()
because it was disposed.
Here are alternative methods that work, but I'd really like to know the optimal method of doing this.
1: Wrap a StreamReader
around the base stream and never dispose it.
public override void OnActionExecuting(HttpActionContext actionContext)
{
StreamReader streamReader = new StreamReader(actionContext.Request.Content.ReadAsStreamAsync().Result);
streamReader.BaseStream.Position = 0;
string rawJson = streamReader.ReadToEnd();
// etc
}
This works well for every attribute but I worry that I might be leaking memory by not disposing the StreamReader
.
2: Copy the base stream to a MemoryStream
and wrap that with a StreamReader
.
public override void OnActionExecuting(HttpActionContext actionContext)
{
MemoryStream memoryStream = new MemoryStream();
Stream s = actionContext.Request.Content.ReadAsStreamAsync().Result;
s.Position = 0;
s.CopyTo(memoryStream);
string rawJson;
using (StreamReader streamReader = new StreamReader(memoryStream))
{
streamReader.BaseStream.Position = 0;
rawJson = streamReader.ReadToEnd();
}
// etc
}
This works well for every attribute but is a lot of code and might be inefficient.
3: Set the base stream's position to 0 then call ReadAsStringAsync
.
public override void OnActionExecuting(HttpActionContext actionContext)
{
actionContext.Request.Content.ReadAsStreamAsync().Result.Position = 0;
string rawJson = actionContext.Request.Content.ReadAsStringAsync().Result;
// etc
}
This works well for every attribute but might be less efficient.
So, is there an optimal way to do this without leaking memory?