J'essaie de lire le corps dans un middleware à des fins d'authentification, mais lorsque la demande parvient au contrôleur api, l'objet est vide car le corps a déjà été lu. Y at-il de toute façon autour de cela. Je lis le corps comme ça dans mon middleware.
var buffer = new byte[ Convert.ToInt32( context.Request.ContentLength ) ];
await context.Request.Body.ReadAsync( buffer, 0, buffer.Length );
var body = Encoding.UTF8.GetString( buffer );
Si vous utilisez application/x-www-form-urlencoded
Ou multipart/form-data
, Vous pouvez appeler en toute sécurité context.Request.ReadFormAsync()
plusieurs fois car il renvoie une instance mise en cache lors des appels suivants.
Si vous utilisez un type de contenu différent, vous devrez tamponner manuellement la demande et remplacer le corps de la demande par un flux rembobinable comme MemoryStream
. Voici comment vous pourriez faire en utilisant un middleware en ligne (vous devez l'enregistrer bientôt dans votre pipeline):
app.Use(next => async context => {
// Keep the original stream in a separate
// variable to restore it later if necessary.
var stream = context.Request.Body;
// Optimization: don't buffer the request if
// there was no stream or if it is rewindable.
if (stream == Stream.Null || stream.CanSeek) {
await next(context);
return;
}
try {
using (var buffer = new MemoryStream()) {
// Copy the request stream to the memory stream.
await stream.CopyToAsync(buffer);
// Rewind the memory stream.
buffer.Position = 0L;
// Replace the request stream by the memory stream.
context.Request.Body = buffer;
// Invoke the rest of the pipeline.
await next(context);
}
}
finally {
// Restore the original stream.
context.Request.Body = stream;
}
});
Vous pouvez également utiliser l'extension BufferingHelper.EnableRewind()
, qui fait partie du package Microsoft.AspNet.Http
: Elle est basée sur une approche similaire mais s'appuie sur un flux spécial qui commence la mise en mémoire tampon des données en mémoire et spoule tout en un fichier temporaire sur le disque lorsque le seuil est atteint:
app.Use(next => context => {
context.Request.EnableRewind();
return next(context);
});
Pour info: un middleware tampon sera probablement ajouté à vNext à l'avenir.
Utilisation de la mention par PinPoint de EnableRewind
Startup.cs
using Microsoft.AspNetCore.Http.Internal;
Startup.Configure(...){
...
//Its important the rewind us added before UseMvc
app.Use(next => context => { context.Request.EnableRewind(); return next(context); });
app.UseMvc()
...
}
Ensuite, dans votre middleware, il vous suffit de rembobiner et de relire
private async Task GenerateToken(HttpContext context)
{
context.Request.EnableRewind();
string jsonData = new StreamReader(context.Request.Body).ReadToEnd();
...
}
Cela fonctionne avec .Net Core 2.1 et supérieur.
Aujourd'hui, je lance dans un problème similaire. En bref, ce qui fonctionnait avec
Body.Seek(0, SeekOrigin.Begin);
a abouti à aujourd'hui en exception, du moins dans mon cas. Cela s'est produit après la migration du code vers la dernière version de .NET Core.
La solution de contournement pour moi était d'ajouter ceci:
app.Use(next => context => { context.Request.EnableBuffering(); return next(context);
Ajoutez ceci avant de configurer des contrôleurs ou MVC. Cela semble être ajouté dans le cadre de la version .NET Core 2.1.
J'espère que cela aide quelqu'un!
Acclamations et codage heureux.