Carlinhos
Carlinhos

Reputation: 970

How to get body value (Stream) from request without clean it?

I'm trying to get body from request of an authorization class (AuthorizationHandler), but that body is a Stream and after reading your content, the post request that comes on next can not be executed because Stream content has been disposable.

I'm using this code to get Stream content:

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;
    }
}

How i can do to workaround this problem ?

Upvotes: 3

Views: 4133

Answers (2)

Walter
Walter

Reputation: 1

Maybe not needed any more, but you can set request.EnableRewind() and then do the request.Body.Seek(0, SeekOrigin.Begin);

Work for me

Upvotes: 0

Aleks Andreev
Aleks Andreev

Reputation: 7054

StreamReader has a special constructor that allow you to pass a boolean as last parameter. It will prevent dispose underlying stream

EDIT: Because ReadToEnd do not restore position in stream you should do it by yourself like this:

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


EDIT 2: From MSDN I see that Body has a setter. So you can replace original Body with memory stream:

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);
}

Upvotes: 4

Related Questions