ASP.NET 核心修改/替换请求正文



我想对HttpContext.Request.Body进行替换。

我尝试在中间件中执行此操作:

public async Task Invoke(HttpContext context)
{
    if (context.Request.Path.Value.Contains("DataSourceResult"))
    {
        var originalBody = new StreamReader(context.Request.Body).ReadToEnd();
        DataSourceRequest dataSource = null;
        try
        {
            dataSource = JsonConvert.DeserializeObject<DataSourceRequest>(originalBody);
        } catch
        {
            await _next.Invoke(context);
        }
        if (dataSource != null && dataSource.Take > 2000)
        {
            dataSource.Take = 2000;
            var bytesToWrite = dataSource.AsByteArray();
            await context.Request.Body.WriteAsync(bytesToWrite, 0, bytesToWrite.Length);
        }
        else
        {
            var bytesToWrite = originalBody.AsByteArray();
            await context.Request.Body.WriteAsync(bytesToWrite, 0, bytesToWrite.Length);
        }
    }
    await _next.Invoke(context);
}

第一个问题是正文只能读取一次,其次,流是只读的,无法写入。

如何修改/替换Request.Body?我需要更改请求正文的属性值。

获取请求正文,读取其内容,进行任何必要的更改(如果有(,然后创建一个新流以沿管道传递。访问后,必须替换请求流。

public async Task Invoke(HttpContext context) {
    var request = context.Request;
    if (request.Path.Value.Contains("DataSourceResult")) {
        //get the request body and put it back for the downstream items to read
        var stream = request.Body;// currently holds the original stream                    
        var originalContent = new StreamReader(stream).ReadToEnd();
        var notModified = true;
        try {
            var dataSource = JsonConvert.DeserializeObject<DataSourceRequest>(originalContent);
            if (dataSource != null && dataSource.Take > 2000) {
                dataSource.Take = 2000;
                var json = JsonConvert.SerializeObject(dataSource);
                //replace request stream to downstream handlers
                var requestContent = new StringContent(json, Encoding.UTF8, "application/json");
                stream = await requestContent.ReadAsStreamAsync();//modified stream
                notModified = false;
            }
        } catch {
            //No-op or log error
        }
        if (notModified) {
            //put original data back for the downstream to read
            var requestData = Encoding.UTF8.GetBytes(originalContent);
            stream = new MemoryStream(requestData);
        }
        request.Body = stream;
    }
    await _next.Invoke(context);
}

就我而言,将 Request.ContentLength 更新为新值也是必要的。我的解决方案是:

string originalContent;
using (StreamReader stream = new StreamReader(context.Request.Body))
{
    originalContent = stream.ReadToEnd();
}
var dataSource = JsonConvert.DeserializeObject<DataSourceRequest>(originalContent);
if (dataSource != null && dataSource.Take > 2000)
    dataSource.Take = 2000;
string json = JsonConvert.SerializeObject(dataSource);
var requestData = Encoding.UTF8.GetBytes(json);
context.Request.Body = new MemoryStream(requestData);
context.Request.ContentLength = context.Request.Body.Length;

最新更新