Làm cách nào để đọc phần thân yêu cầu trong bộ điều khiển webapi lõi asp.net?


104

Tôi đang cố gắng đọc phần thân yêu cầu trong OnActionExecutingphương thức, nhưng tôi luôn nhận được nullphần nội dung.

var request = context.HttpContext.Request;
var stream = new StreamReader(request.Body);
var body = stream.ReadToEnd();

Tôi đã cố gắng đặt rõ ràng vị trí luồng thành 0 nhưng điều đó cũng không hoạt động. Vì đây là ASP.NET CORE, tôi nghĩ mọi thứ hơi khác một chút. Tôi có thể xem tất cả các mẫu ở đây đề cập đến các phiên bản webapi cũ.
Có cách nào khác để làm điều này không?


4
Hãy cẩn thận, nếu nội dung yêu cầu đã được đọc trước đó trong quá trình chuyển yêu cầu, thì nó sẽ trống khi bạn cố gắng đọc nó lần thứ hai
Fabio

1

@Fabio Cảm ơn bạn đã cung cấp thông tin, chúng tôi có thể đặt vị trí và đọc lại không?
Kasun Koswattha

@KasunKoswattha - Theo thiết kế, nội dung nội dung được coi là luồng chuyển tiếp chỉ có thể đọc một lần.
user270576

Tôi đoán câu hỏi nhắm vào các bộ lọc hoặc phần mềm trung gian hơn là bộ điều khiển.
Jim Aho

Câu trả lời:


111

Trong ASP.Net Core, có vẻ phức tạp khi đọc nhiều lần yêu cầu nội dung, tuy nhiên nếu lần thử đầu tiên của bạn thực hiện đúng cách, bạn sẽ ổn cho những lần thử tiếp theo.

Tôi đã đọc một số cách xoay vòng, chẳng hạn bằng cách thay thế luồng nội dung, nhưng tôi nghĩ cách sau là sạch nhất:

Những điểm quan trọng nhất là

  1. để cho yêu cầu biết rằng bạn sẽ đọc nội dung của nó hai lần hoặc nhiều hơn,
  2. để không đóng luồng nội dung và
  3. để tua nó về vị trí ban đầu để quá trình bên trong không bị mất.

[BIÊN TẬP]

Như đã chỉ ra bởi Murad, bạn cũng có thể tận dụng tiện ích mở rộng .Net Core 2.1: EnableBufferingNó lưu trữ các yêu cầu lớn vào đĩa thay vì giữ nó trong bộ nhớ, tránh các vấn đề về luồng lớn được lưu trữ trong bộ nhớ (tệp, hình ảnh, ...) . Bạn có thể thay đổi thư mục tạm thời bằng cách đặt ASPNETCORE_TEMPbiến môi trường và các tệp sẽ bị xóa khi hết yêu cầu.

Trong AuthorizationFilter , bạn có thể làm như sau:

// Helper to enable request stream rewinds
using Microsoft.AspNetCore.Http.Internal;
[...]
public class EnableBodyRewind : Attribute, IAuthorizationFilter
{
    public void OnAuthorization(AuthorizationFilterContext context)
    {
        var bodyStr = "";
        var req = context.HttpContext.Request;

        // Allows using several time the stream in ASP.Net Core
        req.EnableRewind(); 

        // Arguments: Stream, Encoding, detect encoding, buffer size 
        // AND, the most important: keep stream opened
        using (StreamReader reader 
                  = new StreamReader(req.Body, Encoding.UTF8, true, 1024, true))
        {
            bodyStr = reader.ReadToEnd();
        }

        // Rewind, so the core is not lost when it looks the body for the request
        req.Body.Position = 0;

        // Do whatever work with bodyStr here

    }
}



public class SomeController : Controller
{
    [HttpPost("MyRoute")]
    [EnableBodyRewind]
    public IActionResult SomeAction([FromBody]MyPostModel model )
    {
        // play the body string again
    }
}

Sau đó, bạn có thể sử dụng lại phần thân trong trình xử lý yêu cầu.

Trong trường hợp của bạn nếu bạn nhận được kết quả rỗng, có thể có nghĩa là phần nội dung đã được đọc ở giai đoạn trước đó. Trong trường hợp đó, bạn có thể cần sử dụng phần mềm trung gian (xem bên dưới).

Tuy nhiên, hãy cẩn thận nếu bạn xử lý các luồng lớn, hành vi đó ngụ ý rằng mọi thứ đã được tải vào bộ nhớ, điều này sẽ không được kích hoạt trong trường hợp tải lên tệp.

Bạn có thể muốn sử dụng nó như một Middleware

Của tôi trông giống như thế này (một lần nữa, nếu bạn tải xuống / tải lên các tệp lớn, điều này nên được tắt để tránh các vấn đề về bộ nhớ):

public sealed class BodyRewindMiddleware
{
    private readonly RequestDelegate _next;

    public BodyRewindMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext context)
    {
        try { context.Request.EnableRewind(); } catch { }
        await _next(context);
        // context.Request.Body.Dipose() might be added to release memory, not tested
    }
}
public static class BodyRewindExtensions
{
    public static IApplicationBuilder EnableRequestBodyRewind(this IApplicationBuilder app)
    {
        if (app == null)
        {
            throw new ArgumentNullException(nameof(app));
        }

        return app.UseMiddleware<BodyRewindMiddleware>();
    }

}

suối vẫn còn trống rỗng ngay cả khi tôi tua lại để vị trí 0.
Adrian Nasui

2
Bạn đã sử dụng req.EnableRewind();chưa? Tôi sử dụng đoạn mã trên và nó hoạt động tốt.
Jean,

đã sử dụng req.EnableRewind (); không hoạt động. Tôi nhận được Vị trí = 0, chiều dài nội dung = 26, nhưng đọc luồng 'nội dung' xuất hiện một chuỗi trống.
Adrian Nasui

Bạn phải kích hoạt tua lại trước khi đọc đầu tiên của cơ thể và không trước khi một trong 2, nếu bạn không Tôi nghĩ rằng nó sẽ không làm việc
Jean

3
Nó cũng có thể sử dụng request.EnableBuffering()(wrapper hơn EnableRewind()) Nó có sẵn trong ASP.NET 2.1 Lõi docs.microsoft.com/en-us/dotnet/api/...
Murad

27

Một giải pháp rõ ràng hơn, hoạt động trong ASP.Net Core 2.1 / 3.1

Lọc lớp

using Microsoft.AspNetCore.Authorization;
// For ASP.NET 2.1
using Microsoft.AspNetCore.Http.Internal;
// For ASP.NET 3.1
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Filters;

public class ReadableBodyStreamAttribute : AuthorizeAttribute, IAuthorizationFilter
{
    public void OnAuthorization(AuthorizationFilterContext context)
    {
        // For ASP.NET 2.1
        // context.HttpContext.Request.EnableRewind();
        // For ASP.NET 3.1
        // context.HttpContext.Request.EnableBuffering();
    }
}

Trong một bộ điều khiển

[HttpPost]
[ReadableBodyStream]
public string SomePostMethod()
{
    //Note: if you're late and body has already been read, you may need this next line
    //Note2: if "Note" is true and Body was read using StreamReader too, then it may be necessary to set "leaveOpen: true" for that stream.
    HttpContext.Request.Body.Seek(0, SeekOrigin.Begin);

    using (StreamReader stream = new StreamReader(HttpContext.Request.Body))
    {
        string body = stream.ReadToEnd();
        // body = "param=somevalue&param2=someothervalue"
    }
}

2
Đối với netcore3.0, nó sẽ là .EnableBuffering () thay vì.EnableRewind()
mr5

Cảm ơn @ mr5 - Cập nhật câu trả lời của tôi
Andriod

Tôi đã tìm thấy điều này khi sửa một số bản nâng cấp .net Core 2.2 -> Core 3.1 đã làm hỏng cách EnableRewind (). Tôi nghĩ rằng điều này cần một dòng mã nữa, nếu thiếu nó, tôi không thể đọc lại Body: HttpContext.Request.Body.Seek (0, SeekOrigin.Begin);
Larry Smith

2
Điều này chỉ hoạt động đối với tôi sau khi thay đổi AuthorizeAttributethành Attribute(trong ASP.Net Core 3.1).
Sigmund

Các bạn hãy chắc chắn thêm các thư viện đã đề cập. Tôi đã có mã nhưng EnableBuffering hiển thị dòng chữ nguệch ngoạc màu đỏ cho đến khi tôi nhận ra tham chiếu Microsoft.AspNetCore.Http bị thiếu. Cảm ơn Android!
kaarthick raman

18

Để có thể tua lại phần thân yêu cầu, câu trả lời của @ Jean đã giúp tôi đưa ra một giải pháp có vẻ hoạt động tốt. Tôi hiện đang sử dụng điều này cho Phần mềm trung gian xử lý ngoại lệ toàn cầu nhưng nguyên tắc vẫn giống nhau.

Tôi đã tạo một phần mềm trung gian về cơ bản cho phép tua lại trên phần thân yêu cầu (thay vì trình trang trí).

using Microsoft.AspNetCore.Http.Internal;
[...]
public class EnableRequestRewindMiddleware
{
    private readonly RequestDelegate _next;

    public EnableRequestRewindMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext context)
    {
        context.Request.EnableRewind();
        await _next(context);
    }
}

public static class EnableRequestRewindExtension
{
    public static IApplicationBuilder UseEnableRequestRewind(this IApplicationBuilder builder)
    {
        return builder.UseMiddleware<EnableRequestRewindMiddleware>();
    }
}

Điều này sau đó có thể được sử dụng Startup.csnhư vậy của bạn :

[...]
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    [...]
    app.UseEnableRequestRewind();
    [...]
}

Sử dụng phương pháp này, tôi đã có thể tua lại luồng nội dung yêu cầu thành công.


1
Điều này rất hiệu quả với tôi @SaoBiz cảm ơn bạn! một lỗi đánh máy, thay đổi lần thứ 2 này để nhà xây dựng trong UseEnableRequestRewind(this IApplicationBuilder builder).
Richard Logwood

@RichardLogwood Rất vui vì nó đã giúp ích! Cảm ơn vì đã tìm thấy lỗi đánh máy! Đã sửa. :)
SaoBiz

6

Đây là một chủ đề hơi cũ, nhưng kể từ khi tôi đến đây, tôi nghĩ rằng tôi sẽ đăng những phát hiện của mình để chúng có thể giúp những người khác.

Đầu tiên, tôi gặp vấn đề tương tự, nơi tôi muốn nhận Request.Body và làm gì đó với điều đó (ghi nhật ký / kiểm tra). Nhưng nếu không, tôi muốn điểm cuối trông giống nhau.

Vì vậy, có vẻ như lệnh gọi EnableBuffering () có thể thực hiện thủ thuật. Sau đó, bạn có thể thực hiện Tìm kiếm (0, xxx) trên phần thân và đọc lại nội dung, v.v.

Tuy nhiên, điều này dẫn đến vấn đề tiếp theo của tôi. Tôi sẽ nhận được ngoại lệ "Hoạt động đồng bộ không được phép" khi truy cập điểm cuối. Vì vậy, cách giải quyết là đặt thuộc tính AllowSynchronousIO = true, trong các tùy chọn. Có một số cách để thực hiện điều này (nhưng không quan trọng phải chi tiết ở đây ..)

VẬY, vấn đề tiếp theo là khi tôi đọc Request.Body thì nó đã được xử lý. Ặc. Vì vậy, những gì cho?

Tôi đang sử dụng Newtonsoft.JSON làm trình phân tích cú pháp [FromBody] của mình trong lệnh gọi endpiont. Đó là những gì chịu trách nhiệm cho việc đọc đồng bộ và nó cũng đóng luồng khi nó hoàn tất. Giải pháp? Đọc luồng trước khi đến với phân tích cú pháp JSON? Chắc chắn, điều đó hoạt động và tôi đã kết thúc với điều này:

 /// <summary>
/// quick and dirty middleware that enables buffering the request body
/// </summary>
/// <remarks>
/// this allows us to re-read the request body's inputstream so that we can capture the original request as is
/// </remarks>
public class ReadRequestBodyIntoItemsAttribute : AuthorizeAttribute, IAuthorizationFilter
{
    public void OnAuthorization(AuthorizationFilterContext context)
    {
        if (context == null) return;

        // NEW! enable sync IO beacuse the JSON reader apparently doesn't use async and it throws an exception otherwise
        var syncIOFeature = context.HttpContext.Features.Get<IHttpBodyControlFeature>();
        if (syncIOFeature != null)
        {
            syncIOFeature.AllowSynchronousIO = true;

            var req = context.HttpContext.Request;

            req.EnableBuffering();

            // read the body here as a workarond for the JSON parser disposing the stream
            if (req.Body.CanSeek)
            {
                req.Body.Seek(0, SeekOrigin.Begin);

                // if body (stream) can seek, we can read the body to a string for logging purposes
                using (var reader = new StreamReader(
                     req.Body,
                     encoding: Encoding.UTF8,
                     detectEncodingFromByteOrderMarks: false,
                     bufferSize: 8192,
                     leaveOpen: true))
                {
                    var jsonString = reader.ReadToEnd();

                    // store into the HTTP context Items["request_body"]
                    context.HttpContext.Items.Add("request_body", jsonString);
                }

                // go back to beginning so json reader get's the whole thing
                req.Body.Seek(0, SeekOrigin.Begin);
            }
        }
    }
}

Vì vậy, bây giờ, tôi có thể truy cập phần thân bằng cách sử dụng HttpContext.Items ["request_body"] trong các điểm cuối có thuộc tính [ReadRequestBodyIntoItems].

Nhưng anh bạn, điều này có vẻ như có quá nhiều vòng để nhảy qua. Vì vậy, đây là nơi tôi đã kết thúc và tôi thực sự hài lòng với nó.

Điểm cuối của tôi bắt đầu như sau:

[HttpPost("")]
[ReadRequestBodyIntoItems]
[Consumes("application/json")]
public async Task<IActionResult> ReceiveSomeData([FromBody] MyJsonObjectType value)
{
    val bodyString = HttpContext.Items["request_body"];
    // use the body, process the stuff...
}

Nhưng đơn giản hơn nhiều là chỉ cần thay đổi chữ ký, như sau:

[HttpPost("")]
[Consumes("application/json")]
public async Task<IActionResult> ReceiveSomeData()
{
    using (var reader = new StreamReader(
           Request.Body,
           encoding: Encoding.UTF8,
           detectEncodingFromByteOrderMarks: false
    ))
    {
        var bodyString = await reader.ReadToEndAsync();

        var value = JsonConvert.DeserializeObject<MyJsonObjectType>(bodyString);

        // use the body, process the stuff...
    }
}

Tôi thực sự thích điều này vì nó chỉ đọc luồng cơ thể một lần và tôi có quyền kiểm soát quá trình khử trên không. Chắc chắn, thật tuyệt nếu lõi ASP.NET thực hiện điều kỳ diệu này đối với tôi, nhưng ở đây tôi không lãng phí thời gian đọc luồng hai lần (có lẽ mỗi lần lưu vào bộ đệm) và mã khá rõ ràng và sạch sẽ.

Nếu bạn cần chức năng này trên nhiều thiết bị đầu cuối, có lẽ các phương pháp tiếp cận phần mềm trung gian có thể sạch hơn hoặc ít nhất bạn có thể đóng gói phần trích xuất phần thân vào một chức năng mở rộng để làm cho mã ngắn gọn hơn.

Dù sao, tôi không tìm thấy bất kỳ nguồn nào đề cập đến cả 3 khía cạnh của vấn đề này, do đó, bài đăng này. Hy vọng rằng điều này sẽ giúp ai đó!

BTW: Điều này đang sử dụng ASP .NET Core 3.1.


Nếu chương trình không thể phân tích cú pháp chuỗi JSON thành NyObjectType, thì tôi không thể đọc giá trị từ "request_body"
Ericyu67

2

Tôi đã gặp sự cố tương tự khi sử dụng ASP.NET Core 2.1:

  • Tôi cần một phần mềm trung gian tùy chỉnh để đọc dữ liệu ĐÃ ĐĂNG và thực hiện một số kiểm tra bảo mật đối với nó
  • sử dụng bộ lọc ủy quyền là không thực tế, do số lượng lớn các hành động bị ảnh hưởng
  • Tôi phải cho phép các đối tượng ràng buộc trong các hành động ([FromBody] someObject). Cảm ơn đã SaoBizchỉ ra giải pháp này.

Vì vậy, giải pháp rõ ràng là cho phép tua lại yêu cầu, nhưng đảm bảo rằng sau khi đọc nội dung, ràng buộc vẫn hoạt động.

EnableRequestRewindMiddleware

public class EnableRequestRewindMiddleware
{
    private readonly RequestDelegate _next;

    ///<inheritdoc/>
    public EnableRequestRewindMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="context"></param>
    /// <returns></returns>
    public async Task Invoke(HttpContext context)
    {
        context.Request.EnableRewind();
        await _next(context);
    }
}

Startup.cs

(đặt cái này ở đầu phương thức Định cấu hình)

app.UseMiddleware<EnableRequestRewindMiddleware>();

Một số phần mềm trung gian khác

Đây là một phần của phần mềm trung gian yêu cầu giải nén thông tin ĐÃ ĐĂNG để kiểm tra nội dung.

using (var stream = new MemoryStream())
{
    // make sure that body is read from the beginning
    context.Request.Body.Seek(0, SeekOrigin.Begin);
    context.Request.Body.CopyTo(stream);
    string requestBody = Encoding.UTF8.GetString(stream.ToArray());

    // this is required, otherwise model binding will return null
    context.Request.Body.Seek(0, SeekOrigin.Begin);
}

2

Gần đây, tôi đã tìm thấy một giải pháp rất thanh lịch sử dụng JSON ngẫu nhiên mà bạn không biết cấu trúc:

    [HttpPost]
    public JsonResult Test([FromBody] JsonElement json)
    {
        return Json(json);
    }

Chỉ đơn giản vậy thôi.


1

Các IHttpContextAccessorphương pháp làm việc nếu bạn muốn đi tuyến đường này.

TLDR;

  • Tiêm IHttpContextAccessor

  • Tua lại - HttpContextAccessor.HttpContext.Request.Body.Seek(0, System.IO.SeekOrigin.Begin);

  • Đọc -- System.IO.StreamReader sr = new System.IO.StreamReader(HttpContextAccessor.HttpContext.Request.Body); JObject asObj = JObject.Parse(sr.ReadToEnd());

Thêm - Cố gắng lấy một ví dụ ngắn gọn, không biên dịch, về các mục bạn cần đảm bảo có sẵn để có thể sử dụng được IHttpContextAccessor. Các câu trả lời đã chỉ ra một cách chính xác rằng bạn sẽ cần phải tìm lại từ đầu khi cố đọc phần nội dung yêu cầu. Các CanSeek, Positiontài sản trên cơ thể yêu cầu dòng hữu ích cho việc xác minh này.

Tài liệu .NET Core DI

// First -- Make the accessor DI available
//
// Add an IHttpContextAccessor to your ConfigureServices method, found by default
// in your Startup.cs file:
// Extraneous junk removed for some brevity:
public void ConfigureServices(IServiceCollection services)
{
    // Typical items found in ConfigureServices:
    services.AddMvc(config => { config.Filters.Add(typeof(ExceptionFilterAttribute)); });
    // ...

    // Add or ensure that an IHttpContextAccessor is available within your Dependency Injection container
    services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
}

// Second -- Inject the accessor
//
// Elsewhere in the constructor of a class in which you want
// to access the incoming Http request, typically 
// in a controller class of yours:
public class MyResourceController : Controller
{
    public ILogger<PricesController> Logger { get; }
    public IHttpContextAccessor HttpContextAccessor { get; }

    public CommandController(
        ILogger<CommandController> logger,
        IHttpContextAccessor httpContextAccessor)
    {
        Logger = logger;
        HttpContextAccessor = httpContextAccessor;
    }

    // ...

    // Lastly -- a typical use 
    [Route("command/resource-a/{id}")]
    [HttpPut]
    public ObjectResult PutUpdate([FromRoute] string id, [FromBody] ModelObject requestModel)
    {
        if (HttpContextAccessor.HttpContext.Request.Body.CanSeek)
        {
            HttpContextAccessor.HttpContext.Request.Body.Seek(0, System.IO.SeekOrigin.Begin);
            System.IO.StreamReader sr = new System.IO.StreamReader(HttpContextAccessor.HttpContext.Request.Body);
            JObject asObj = JObject.Parse(sr.ReadToEnd());

            var keyVal = asObj.ContainsKey("key-a");
        }
    }
}    

1

Tôi đã có thể đọc phần thân yêu cầu trong một ứng dụng asp.net core 3.1 như thế này (cùng với một phần mềm trung gian đơn giản cho phép bộ đệm -enable rewinding dường như đang hoạt động đối với các phiên bản .Net Core trước đó-):

var reader = await Request.BodyReader.ReadAsync();
Request.Body.Position = 0;
var buffer = reader.Buffer;
var body = Encoding.UTF8.GetString(buffer.FirstSpan);
Request.Body.Position = 0;

0

để đọc Body, bạn có thể đọc không đồng bộ.

sử dụng asyncphương pháp như sau:

public async Task<IActionResult> GetBody()
{
      string body="";
      using (StreamReader stream = new StreamReader(Request.Body))
      {
           body = await stream.ReadToEndAsync();
      }
    return Json(body);
}

Kiểm tra với người đưa thư:

nhập mô tả hình ảnh ở đây

Nó hoạt động tốt và đã được thử nghiệm trong Asp.net corephiên bản 2.0 , 2.1 , 2.2, 3.0.

Tôi hy vọng là hữu ích.


0

Tôi cũng muốn đọc Request.Body mà không tự động ánh xạ nó tới một số mô hình tham số hành động. Đã thử nghiệm rất nhiều cách khác nhau trước khi giải quyết vấn đề này. Và tôi không tìm thấy bất kỳ giải pháp làm việc nào được mô tả ở đây. Giải pháp này hiện dựa trên khuôn khổ .NET Core 3.0.

reader.readToEnd () được kết hợp giống như một cách đơn giản, ngay cả khi nó được biên dịch, nó vẫn ném ra một ngoại lệ thời gian chạy yêu cầu tôi sử dụng lệnh gọi không đồng bộ. Vì vậy, thay vào đó tôi đã sử dụng ReadToEndAsync (), tuy nhiên đôi khi nó hoạt động và đôi khi không. Cho tôi các lỗi như, không thể đọc sau khi luồng bị đóng. Vấn đề là chúng tôi không thể đảm bảo rằng nó sẽ trả về kết quả trong cùng một luồng (ngay cả khi chúng tôi sử dụng await). Vì vậy, chúng tôi cần một số loại gọi lại. Giải pháp này đã làm việc cho tôi.

[Route("[controller]/[action]")]
public class MyController : ControllerBase
{

    // ...

    [HttpPost]
    public async void TheAction()
    {
        try
        {
            HttpContext.Request.EnableBuffering();
            Request.Body.Position = 0;
            using (StreamReader stream = new StreamReader(HttpContext.Request.Body))
            {
                var task = stream
                    .ReadToEndAsync()
                    .ContinueWith(t => {
                        var res = t.Result;
                        // TODO: Handle the post result!
                    });

                // await processing of the result
                task.Wait();
            }
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Failed to handle post!");
        }
    }

0

Cách đơn giản nhất có thể để làm điều này là như sau:

  1. Trong phương thức Bộ điều khiển, bạn cần trích xuất nội dung từ đó, hãy thêm tham số này: [FromBody] Giá trị SomeClass

  2. Khai báo "SomeClass" là: class SomeClass {public string SomeParameter {get; bộ; }}

Khi phần thân thô được gửi dưới dạng json, lõi .net biết cách đọc nó rất dễ dàng.


0

Đối với những người chỉ muốn lấy nội dung (nội dung yêu cầu) từ yêu cầu:

Sử dụng [FromBody]thuộc tính trong tham số phương thức bộ điều khiển của bạn.

[Route("api/mytest")]
[ApiController]
public class MyTestController : Controller
{
    [HttpPost]
    [Route("content")]
    public async Task<string> ReceiveContent([FromBody] string content)
    {
        // Do work with content
    }
}

Như doc đã nói: thuộc tính này chỉ định rằng một tham số hoặc thuộc tính phải được ràng buộc bằng cách sử dụng phần thân yêu cầu.


0

Một cách nhanh chóng để thêm bộ đệm phản hồi trong .NET Core 3.1 là

    app.Use((context, next) =>
    {
        context.Request.EnableBuffering();
        return next();
    });

trong Startup.cs. Tôi thấy điều này cũng đảm bảo rằng bộ đệm sẽ được bật trước khi luồng được đọc, đây là vấn đề đối với .Net Core 3.1 với một số câu trả lời của bộ lọc ủy quyền / phần mềm trung gian khác mà tôi đã thấy.

Sau đó, bạn có thể đọc nội dung yêu cầu của mình thông qua HttpContext.Request.Bodytrình xử lý của bạn như một số người khác đã đề xuất.

Cũng đáng xem xét là EnableBufferingcó quá tải cho phép bạn giới hạn dung lượng nó sẽ lưu vào bộ nhớ trước khi nó sử dụng tệp tạm thời và cũng là giới hạn tổng thể cho bộ đệm của bạn. NB nếu một yêu cầu vượt quá giới hạn này, một ngoại lệ sẽ được đưa ra và yêu cầu sẽ không bao giờ đến được trình xử lý của bạn.


Điều này đã hoạt động tuyệt vời đối với tôi (3,1). Đã trích dẫn cho bạn một câu hỏi khác: stackoverflow.com/a/63525694/6210068
Lance
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.