0

我有多个 Attribute 类需要访问 an HttpContent(在 an HttpActionContext's中HttpRequstMessage)中的数据,但我在决定最好的方法时遇到问题。我考虑使用 上的ReadAsStringAsync方法HttpContent,但似乎我需要访问Stream才能首先将位置设置为 0。

天真的方式似乎只是用这样的语句StreamReader将基本流包裹起来:using

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
}

这适用于执行的第一个属性,但执行的每个后续属性都会引发异常,actionContext.Request.Content.ReadAsStreamAsync()因为它已被释放。

以下是可行的替代方法,但我真的很想知道这样做的最佳方法。

1:将 a 包裹StreamReader在基本流周围并且永远不要丢弃它。

public override void OnActionExecuting(HttpActionContext actionContext)
{
  StreamReader streamReader = new StreamReader(actionContext.Request.Content.ReadAsStreamAsync().Result);
  streamReader.BaseStream.Position = 0;
  string rawJson = streamReader.ReadToEnd();     
  // etc
}

这适用于每个属性,但我担心我可能会因为不处理StreamReader.

2:将基本流复制到 aMemoryStream并用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
}

这适用于每个属性,但代码量很大,可能效率低下

3:将基本流的位置设置为0,然后调用ReadAsStringAsync

public override void OnActionExecuting(HttpActionContext actionContext)
{
  actionContext.Request.Content.ReadAsStreamAsync().Result.Position = 0;
  string rawJson = actionContext.Request.Content.ReadAsStringAsync().Result;
  // etc
}

这适用于每个属性,但可能效率较低

那么,有没有一种不泄漏内存的最佳方法呢?

4

1 回答 1

0

使用使流保持打开状态的流阅读器 - 因为您不拥有流的所有权,它仍然在 HTTP 操作内容的范围内拥有。

public StreamReader (System.IO.Stream stream, System.Text.Encoding encoding, bool detectEncodingFromByteOrderMarks, int bufferSize, bool leaveOpen);

可以选择让流保持打开状态的构造函数

由于可能出现死锁,使用 .Result 在同步上下文中完成异步调用也是有风险的。尝试将您的方法重构为异步。

于 2020-04-15T15:59:19.160 回答