【问题标题】:How to get body value (Stream) from request without clean it?如何在不清理请求的情况下从请求中获取正文值(流)?
【发布时间】:2017-12-30 03:59:01
【问题描述】:

我正在尝试从授权类 (AuthorizationHandler) 的请求中获取正文,但该正文是一个 Stream,并且在阅读了您的内容后,由于 Stream 内容是一次性的,因此无法执行接下来的发布请求。

我正在使用此代码获取 Stream 内容:

protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, Autorizacao requirement)
{
    var routeValues = context.Resource as AuthorizationFilterContext;
    if (routeValues != null)
    {
        var obj = StreamToObject(routeValues.HttpContext.Request.Body);
        context.Succeed(requirement);
    }
    return Task.FromResult(0);
}

private Object StreamToObject(Stream stream)
{
    try
    {
        string content;
        using (var reader = new StreamReader(stream))
        content = reader.ReadToEnd();
        return Newtonsoft.Json.JsonConvert.DeserializeObject(content);
    }
    catch (Exception e)
    {
        throw e;
    }
}

我该如何解决这个问题?

【问题讨论】:

标签: c# asp.net asp.net-web-api


【解决方案1】:

可能不再需要了,但您可以设置request.EnableRewind(),然后执行request.Body.Seek(0, SeekOrigin.Begin);

为我工作

【讨论】:

    【解决方案2】:

    StreamReader 有一个特殊的constructor,它允许您将布尔值作为最后一个参数传递。它将防止处理底层流

    编辑: 因为ReadToEnd 不恢复流中的位置,所以您应该自己这样做:

    var position = stream.Position;
    using (var reader = new StreamReader(stream, Encoding.UTF8, false, 8192, true))
        content = reader.ReadToEnd();
    stream.Seek(position, SeekOrigin.Begin);
    


    编辑 2:MSDN 我看到 Body 有一个二传手。所以你可以用内存流替换原来的Body

    if (routeValues != null)
    {
        var memoryStream = new MemoryStream();
        routeValues.HttpContext.Request.Body.CopyTo(memoryStream);
    
        // reset position after CopyTo
        memoryStream.Seek(0, SeekOrigin.Begin);
        var obj = StreamToObject(memoryStream);
    
        // reset position after ReadToEnd
        memoryStream.Seek(0, SeekOrigin.Begin);
        routeValues.HttpContext.Request.Body = memoryStream;
        context.Succeed(requirement);
    }
    

    【讨论】:

    • 如果流被阻止被释放,使用块是什么?
    • @deezg 只是一种编码风格的习惯。通常我被包围甚至内存流到using(有一个空的Dispose
    • 是的,是的,当然,这里也一样;)。我想说明另一点:对于不够小心的人来说,这可能是一件危险的事情,因为通常读取器会处理底层流,但这样using for reader 不会处理流,因此应该在使用后手动完成。跨度>
    • 我尝试使用您的代码,但是我获得的 AuthorizationFilterContext 类的流属性无法获取您的位置属性,因为抛出异常“不支持指定的方法”。我不知道发生了什么。
    • @Carlinhos 看起来您的流不支持 Seek 方法。您能否更新一个问题,以便我查看您如何获得 stream 变量?
    猜你喜欢
    • 2011-12-26
    • 2013-07-31
    • 2016-06-15
    • 2021-01-07
    • 2014-05-17
    • 1970-01-01
    • 1970-01-01
    • 2011-09-05
    • 2017-02-13
    相关资源
    最近更新 更多