web-dev-qa-db-fra.com

Comment lire le corps de demande de demande multiple dans ASP Net Core 2.2 Middleware?

J'ai essayé ceci: Lire la demande de demande deux fois Et ceci: https://github.com/aspnet/mvc/issues/4962 mais n'a pas fonctionné. J'ai lu la demande corporelle comme ceci:

app.Use(async (context, next) =>
{
    var requestBody = await ReadStream(context.Request.Body);
    var requestPath = context.Request.Path.ToString();
    //Do some thing

    await next.Invoke();

    var responseStatusCode = context.Response.StatusCode;
    //Do some other thing
});

private async Task<string> ReadStream(Stream stream)
{
    using (var streamReader = new StreamReader(stream))
    {
        var result = await streamReader.ReadToEndAsync();

        return result;
    }
}

Dans le contrôleur, je reçois un "objet disposé" ou "flux vide".

9
Alireza Yavari

Lorsque le flux est lu la deuxième fois, le pointeur de flux est réglé sur la dernière position. Vous devriez essayer de le déplacer à la position de zéro pour la lire à nouveau depuis le début.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.WebUtilities;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using NLog;

namespace Test_Middlewares.Middlewares
{
    // You may need to install the Microsoft.AspNetCore.Http.Abstractions package into your project
    public class LoggingMiddleware
    {
        private readonly RequestDelegate _next;
        private readonly ILogger<LoggingMiddleware> _logger;

        public LoggingMiddleware(RequestDelegate next, ILogger<LoggingMiddleware> logger)
        {
            _next = next;
            _logger = logger;
        }

        public async Task InvokeAsync(HttpContext httpContext)
        {
            var HttpContextBody = httpContext.Request.Body;
            string requestBody = "";

            httpContext.Request.EnableBuffering();

            // Leave the body open so the next middleware can read it.
            using (var reader = new StreamReader(
                httpContext.Request.Body,
                encoding: Encoding.UTF8,
                detectEncodingFromByteOrderMarks: false,
                bufferSize: -1,
                leaveOpen: true))
            {
                var body = await reader.ReadToEndAsync();
                // Do some processing with body…

                // Reset the request body stream position so the next middleware can read it
                httpContext.Request.Body.Position = 0;
            }

            _logger.LogDebug("Middleware 1 body =" + requestBody);

            await _next.Invoke(httpContext);
        }
    }

    // Extension method used to add the middleware to the HTTP request pipeline.
    public static class LoggingMiddlewareExtensions
    {
        public static IApplicationBuilder UseLoggingMiddleware(this IApplicationBuilder builder)
        {
            return builder.UseMiddleware<LoggingMiddleware>();
        }
    }
}

Pour plus d'informations, reportez-vous à ces liens:

https://devblogs.microsoft.com/aspnet/re-reading-asp-net-core-request-bodies-with-enableBuffering/

https://gunnarpeipman.com/aspnet-core-request-body/

0
Houssam Nasser

Je me luttais autour de lui, .Net Core 3.1 a des changements ruptiers: "Contexte.Request.Nablerewind ();" n'est plus disponible dans .NET CORE 3.1, astuces plus utiles visitez ici

Code de travail dans ASP.NET MVC API .NET CORE 3.1 (startup.cs)

            app.Use(async (context, next) =>
        {
            context.Request.EnableBuffering();
            var stream = context.Request.Body;

            using (var reader = new StreamReader(stream))
            {
                var requestBodyAsString = await reader.ReadToEndAsync();

                if (stream.CanSeek)
                    stream.Seek(0, SeekOrigin.Begin);
               
                //some logging and other stuff goes here

                await next.Invoke();

            }
        });
0
Surya-AIS

.NETCORE 3.1 Version de la réponse de @ Houssamnasser ci-dessus. J'ai créé une fonction réutilisable pour lire le corps de la demande. Veuillez noter le changement: HttpRequestRewindExtensions.EnableBuffering(request). EnableBuffering est maintenant une partie de HTTPeQuRewindexsions classe.

public async Task<JObject> GetRequestBodyAsync(HttpRequest request)
    {
        JObject objRequestBody = new JObject();

        // IMPORTANT: Ensure the requestBody can be read multiple times.
        HttpRequestRewindExtensions.EnableBuffering(request);

        // IMPORTANT: Leave the body open so the next middleware can read it.
        using (StreamReader reader = new StreamReader(
            request.Body,
            Encoding.UTF8,
            detectEncodingFromByteOrderMarks: false,
            leaveOpen: true))
        {
            string strRequestBody = await reader.ReadToEndAsync();
            objRequestBody = SerializerExtensions.Deserialize<JObject>(strRequestBody);

            // IMPORTANT: Reset the request body stream position so the next middleware can read it
            request.Body.Position = 0;
        }

        return objRequestBody;
    }

Cette fonction retournera un travail professionnel pouvant être utilisé pour lire les propriétés de l'objet corporel de la demande. Serializeextensions est mon extension personnalisée pour la sérialisation et la désérialisation.

Dans le middleware, vous pouvez injecter IHttpContextAccessor httpContextAccessor Dans le constructeur. Puis accédez à l'objet de la demande comme HttpRequest request = _httpContextAccessor.HttpContext.Request;. Enfin, peut appeler la fonction réutilisable comme GetRequestBodyAsync(request)