Для дублированного html это вызвано await _next(context);
в UpdateHtml
, который вызовет промежуточное программное обеспечение, такое как MVC, для обработки запросов и ответов.
Без await _next(context);
не следует изменять тело ответа в context.Response.OnStarting
.
В качестве обходного пути я бы предложил вам установить ResponseMeasurementMiddleware
в качестве первого промежуточного программного обеспечения, а затем рассчитать время, например
public class ResponseMeasurementMiddleware
{
private readonly RequestDelegate _next;
public ResponseMeasurementMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
var originalBody = context.Response.Body;
var newBody = new MemoryStream();
context.Response.Body = newBody;
var watch = new Stopwatch();
long responseTime = 0;
watch.Start();
await _next(context);
//// read the new body
// read the new body
responseTime = watch.ElapsedMilliseconds;
newBody.Position = 0;
var newContent = await new StreamReader(newBody).ReadToEndAsync();
// calculate the updated html
var updatedHtml = CreateDataNode(newContent, responseTime);
// set the body = updated html
var updatedStream = GenerateStreamFromString(updatedHtml);
await updatedStream.CopyToAsync(originalBody);
context.Response.Body = originalBody;
}
public static Stream GenerateStreamFromString(string s)
{
var stream = new MemoryStream();
var writer = new StreamWriter(stream);
writer.Write(s);
writer.Flush();
stream.Position = 0;
return stream;
}
private string CreateDataNode(string originalHtml, long responseTime)
{
var htmlDoc = new HtmlDocument();
htmlDoc.LoadHtml(originalHtml);
HtmlNode testNode = HtmlNode.CreateNode($"<div><h2>Inserted using Html Agility Pack: Response Time: {responseTime.ToString()} ms.</h2><div>");
var htmlBody = htmlDoc.DocumentNode.SelectSingleNode("//body");
htmlBody.InsertBefore(testNode, htmlBody.FirstChild);
string rawHtml = htmlDoc.DocumentNode.OuterHtml; //using this results in a page that displays my inserted HTML correctly, but duplicates the original page content.
//rawHtml = "some text"; uncommenting this results in a page with the correct format: this text, followed by the original contents of the page
return rawHtml;
}
}
, и зарегистрировать ResponseMeasurementMiddleware
, например
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseMiddleware<ResponseMeasurementMiddleware>();
//rest middlwares
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
Для этого пути app.UseMiddleware<ResponseMeasurementMiddleware>();
действие будет последним действием перед отправкой ответа, и тогда время обработки будет подходящим для времени обработки.