就这么简单,我试图用另一个流替换我的 context.HttpContext.Response.Body 。
我已经走了这么远,我可以劫持流,但替换它不起作用。现在我在这个例子中使用了 Weatherforecast web-api 模板。
public override void OnResultExecuted(ResultExecutedContext context)
{
responseBody.Seek(0, SeekOrigin.Begin);
var originalBody = context.HttpContext.Response.Body;
using var sr = new StreamReader(responseBody);
var actionResult = sr.ReadToEnd();
using var memStream = new MemoryStream();
context.HttpContext.Response.Body = memStream;
var fake = actionResult.Replace("Warm", "REPLACED", StringComparison.InvariantCultureIgnoreCase).Replace("Hot", "REPLACED", StringComparison.InvariantCultureIgnoreCase);
memStream.Position = 0;
var data = GetStreamWithGetBytes(fake, Encoding.UTF8);
memStream.Write(data, 0, data.Length);
memStream.Position = 0;
memStream.CopyToAsync(originalBody);
context.HttpContext.Response.Body = originalBody;
}
如您所见,我正在用 REPLACED 替换“温暖”或“热”
替换工作正常,但是分配更改的数据并将其读入流中并返回上下文。HttpContext.Response.Body 似乎不起作用。
请问我错过了什么?
我不是在寻找中间件解决方案。我想用我的自定义动作过滤器来装饰我们的控制器。所以必须用actionfilterattribute或者IActionFilter来实现。
完整代码如下:
public class MessageFilter : ActionFilterAttribute
{
private MemoryStream responseBody;
public override void OnActionExecuting(ActionExecutingContext context)
{
//context.HttpContext.Request.EnableBuffering();
this.responseBody = new MemoryStream();
//hijack the real stream with our own memory stream
context.HttpContext.Response.Body = responseBody;
}
public override void OnActionExecuted(ActionExecutedContext context)
{
}
public override void OnResultExecuted(ResultExecutedContext context)
{
responseBody.Seek(0, SeekOrigin.Begin);
var originalBody = context.HttpContext.Response.Body;
using var sr = new StreamReader(responseBody);
var actionResult = sr.ReadToEnd();
using var memStream = new MemoryStream();
context.HttpContext.Response.Body = memStream;
var fake = actionResult.Replace("Warm", "REPLACED", StringComparison.InvariantCultureIgnoreCase).Replace("Hot", "REPLACED", StringComparison.InvariantCultureIgnoreCase);
memStream.Position = 0;
var data = GetStreamWithGetBytes(fake, Encoding.UTF8);
memStream.Write(data, 0, data.Length);
memStream.Position = 0;
memStream.CopyToAsync(originalBody);
context.HttpContext.Response.Body = originalBody;
}
public static byte[] GetStreamWithGetBytes(string sampleString, Encoding? encoding = null)
{
encoding ??= Encoding.UTF8;
var byteArray = encoding.GetBytes(sampleString);
return byteArray;
}
}
控制器类:
using Microsoft.AspNetCore.Mvc;
using WebApplicationHttpMessageHandler.Filters;
namespace WebApplicationHttpMessageHandler.Controllers;
[ApiController]
[Route("[controller]/[action]")]
public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
private readonly ILogger<WeatherForecastController> _logger;
public WeatherForecastController(ILogger<WeatherForecastController> logger)
{
_logger = logger;
}
[HttpGet(Name = "GetWeatherForecast")]
[ServiceFilter(typeof(MessageFilter))]
public IEnumerable<WeatherForecast> Get()
{
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
}
}
我真的被困在这里了。
更改
MessageFilter
如下:
using Microsoft.AspNetCore.Mvc.Filters;
using System.Text.Json;
using Microsoft.AspNetCore.Mvc;
public class MessageFilter : ActionFilterAttribute
{
public override async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
{
if (context.Result is not ObjectResult result)
{
await base.OnResultExecutionAsync(context, next);
return;
}
var data = JsonSerializer.Serialize(result.Value);
var fake = data.Replace("Warm", "REPLACED", StringComparison.InvariantCultureIgnoreCase).Replace("Hot", "REPLACED", StringComparison.InvariantCultureIgnoreCase);
context.HttpContext.Response.ContentType = "application/json";
await context.HttpContext.Response.WriteAsync(fake);
}
}