#c# #asp.net-core
#c# #asp.net-core
Вопрос:
Я пытаюсь захватить все заголовки ответов для всех ответов в веб-API, но HttpContext.Response .Коллекция заголовков всегда пуста. В настоящее время я использую .NET Core и ASP.Net Ядро 3.1.
Реализация начинается с Startup.cs, куда добавляется промежуточное программное обеспечение.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseMiddleware<CaptureResponseHeaders>();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
Далее класс промежуточного программного обеспечения
public class CaptureResponseHeaders
{
public CaptureResponseHeaders(RequestDelegate next)
{
_next = next;
}
private readonly RequestDelegate _next;
public async Task Invoke(HttpContext httpContext)
{
if(httpContext.Response.Headers.Count > 0) //this is always zero.
И запрос, простая конечная точка Get API
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private readonly ILogger<WeatherForecastController> _logger;
public WeatherForecastController(ILogger<WeatherForecastController> logger)
{
_logger = logger;
}
[HttpGet]
public IEnumerable<WeatherForecast> Get()
{
var rng = new Random();
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = rng.Next(-20, 55),
Summary = Summaries[rng.Next(Summaries.Length)]
})
.ToArray();
}
И заголовки ответов, которые я ожидаю захватить
content-type: application/json; charset=utf-8
date: Mon, 14 Dec 2020 18:47:43 GMT
server: Microsoft-IIS/10.0
x-powered-by: ASP.NET
Комментарии:
1. Хотя ответ от Питера Расмуссена звучит неплохо, мне кажется, что все, что вам нужно сделать, это убедиться, что ваше промежуточное программное обеспечение сначала добавлено в конвейер, чтобы оно было последним в ответе, разверните и используйте
await _next()
перед любой вашей логикойInvoke(...)
для получения заголовков.
Ответ №1:
Вы можете сделать следующее в своем методе invoke:
public async Task Invoke(HttpContext context)
{
context.Response.OnStarting(state => {
var httpContext = (HttpContext)state;
if (httpContext.Response.Headers.Count > 0)
CaptureHeaders(); //TODO your implementation
return Task.CompletedTask;
}, context);
await _next(context);
}
Это позволяет захватить ответ прямо перед его отправкой клиенту. Вы также можете использовать OnCompleted для получения ответа после его отправки.
Изображение заголовков можно увидеть ниже:
Комментарии:
1. Заголовок ‘Content-Length’ никогда не существует для меня, я думаю, это потому, что ответ передается потоком, поэтому на данный момент он недоступен… есть идеи, как получить его, не читая поток?
Ответ №2:
Насколько я понимаю, если вы переместите добавление вашего промежуточного программного обеспечения вверх по стеку, оно будет выполнено раньше для запроса и позже для ответа.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
// here
app.UseMiddleware<CaptureResponseHeaders>();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
Что касается нуля, который вы продолжаете видеть, попробуйте поместить свою логику захвата после выполнения остальной части конвейера.
public async Task Invoke(HttpContext httpContext)
{
await _next();
if(httpContext.Response.Headers.Count > 0)
{
// do responsive things
}
}