Analyzing your prompt, please hold on...
An error occurred while retrieving the results. Please refresh the page and try again.
To log HTML conversion time in C#, add custom message handlers to the Aspose.HTML for .NET pipeline: one handler resolves resources from a ZIP archive, while paired logging handlers measure request execution time before rendering the document to PDF.
Performance diagnostics often start with one question: how long does the loading and rendering workflow take? In this example, custom message handlers are chained together to convert an HTML-based file from a ZIP archive to PDF and log the request execution time.
First, create a handler that can participate in a custom schema or protocol implementation. Take the following steps:
CustomSchemaMessageHandler class derived from the
MessageHandler class.CustomSchemaMessageHandler class and define a Filter property for it.CustomSchemaMessageFilter class derived from the
MessageFilter class.The following code snippet shows how to create the CustomSchemaMessageHandler class:
1// Monitor network requests by custom protocol in C # using schema-based message filter and handler
2
3// Define the CustomSchemaMessageFilter class that is derived from the MessageFilter class
4class CustomSchemaMessageFilter : MessageFilter
5{
6 private readonly string schema;
7 public CustomSchemaMessageFilter(string schema)
8 {
9 this.schema = schema;
10 }
11 // Override the Match() method
12 public override bool Match(INetworkOperationContext context)
13 {
14 return string.Equals(schema, context.Request.RequestUri.Protocol.TrimEnd(':'));
15 }
16}
17
18// Define the CustomSchemaMessageHandler class that is derived from the MessageHandler class
19abstract class CustomSchemaMessageHandler : MessageHandler
20{
21 // Initialize an instance of the CustomSchemaMessageHandler class
22 protected CustomSchemaMessageHandler(string schema)
23 {
24 Filters.Add(new CustomSchemaMessageFilter(schema));
25 }
26}The CustomSchemaMessageHandler(schema) constructor instantiates the CustomSchemaMessageHandler object and takes schema as a parameter. The Add() method appends the CustomSchemaMessageFilter object at the end of the collection. The Match() method tests whether a context satisfies the filter criteria.
The following code snippet shows how to create the ZipFileSchemaMessageHandler class for working with ZIP archives:
1// Handle zip file protocol requests in c#
2
3// Define the ZipFileSchemaMessageHandler class that is derived from the CustomSchemaMessageHandler class
4class ZipFileSchemaMessageHandler : CustomSchemaMessageHandler
5{
6 private readonly Archive archive;
7
8 public ZipFileSchemaMessageHandler(Archive archive) : base("zip-file")
9 {
10 this.archive = archive;
11 }
12
13 // Override the Invoke() method
14 public override void Invoke(INetworkOperationContext context)
15 {
16 string pathInsideArchive = context.Request.RequestUri.Pathname.TrimStart('/').Replace("\\", "/");
17 Stream stream = GetFile(pathInsideArchive);
18
19 if (stream != null)
20 {
21 // If a resource is found in the archive, then return it as a Response
22 ResponseMessage response = new ResponseMessage(HttpStatusCode.OK);
23 response.Content = new StreamContent(stream);
24 response.Headers.ContentType.MediaType = MimeType.FromFileExtension(context.Request.RequestUri.Pathname);
25 context.Response = response;
26 }
27 else
28 {
29 context.Response = new ResponseMessage(HttpStatusCode.NotFound);
30 }
31
32 // Invoke the next message handler in the chain
33 Next(context);
34 }
35
36 Stream GetFile(string path)
37 {
38 ArchiveEntry result = archive
39 .Entries
40 .FirstOrDefault(x => x.Name == path);
41 return result?.Open();
42 }
43}In the above example, searching for a resource (zip archive) at its URI is realized. If a resource is found, FromFileExtension() method returns the MimeType of the resource.
The following code snippet shows how to create StartRequestDurationLoggingMessageHandler and StopRequestDurationLoggingMessageHandler to log the time taken for web request execution.
1// Track and log HTTP request durations using C# message handlers
2
3// Define the RequestDurationLoggingMessageHandler class that is derived from the MessageHandler class
4abstract class RequestDurationLoggingMessageHandler : MessageHandler
5{
6 private static ConcurrentDictionary<Url, Stopwatch> requests = new ConcurrentDictionary<Url, Stopwatch>();
7
8 protected void StartTimer(Url url)
9 {
10 requests.TryAdd(url, Stopwatch.StartNew());
11 }
12
13 protected TimeSpan StopTimer(Url url)
14 {
15 Stopwatch timer = requests[url];
16 timer.Stop();
17 return timer.Elapsed;
18 }
19}
20
21class StartRequestDurationLoggingMessageHandler : RequestDurationLoggingMessageHandler
22{
23 // Override the Invoke() method
24 public override void Invoke(INetworkOperationContext context)
25 {
26 // Start the stopwatch
27 StartTimer(context.Request.RequestUri);
28
29 // Invoke the next message handler in the chain
30 Next(context);
31 }
32}
33
34class StopRequestDurationLoggingMessageHandler : RequestDurationLoggingMessageHandler
35{
36 // Override the Invoke() method
37 public override void Invoke(INetworkOperationContext context)
38 {
39 // Stop the stopwatch
40 TimeSpan duration = StopTimer(context.Request.RequestUri);
41
42 // Print the result
43 Debug.WriteLine($"Elapsed: {duration:g}, resource: {context.Request.RequestUri.Pathname}");
44
45 // Invoke the next message handler in the chain
46 Next(context);
47 }
48}The key concept of message handlers is chaining them together. This example uses several handlers, so the order matters. Add them to the pipeline in a specific sequence to resolve ZIP resources and log execution time during HTML to PDF rendering.
To log conversion time:
ZipFileSchemaMessageHandler to resolve resources from the ZIP archive.StartRequestDurationLoggingMessageHandler at the beginning of the pipeline.StopRequestDurationLoggingMessageHandler at the end of the pipeline.HTMLDocument with the configured pipeline. 1// Implement custom zip schema with request duration logging using C# message handlers
2
3// Add this line before you try to use the 'IBM437' encoding
4System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
5
6// Prepare path to a source zip file
7string documentPath = Path.Combine(DataDir, "test.zip");
8
9// Prepare path for converted file saving
10string savePath = Path.Combine(OutputDir, "zip-to-pdf-duration.pdf");
11
12// Create an instance of the Configuration class
13using Configuration configuration = new Configuration();
14INetworkService service = configuration.GetService<INetworkService>();
15MessageHandlerCollection handlers = service.MessageHandlers;
16
17// Custom Schema: ZIP. Add ZipFileSchemaMessageHandler to the end of the pipeline
18handlers.Add(new ZipFileSchemaMessageHandler(new Archive(documentPath)));
19
20// Duration Logging. Add the StartRequestDurationLoggingMessageHandler at the first place in the pipeline
21handlers.Insert(0, new StartRequestDurationLoggingMessageHandler());
22
23// Add the StopRequestDurationLoggingMessageHandler to the end of the pipeline
24handlers.Add(new StopRequestDurationLoggingMessageHandler());
25
26// Initialize an HTML document with specified configuration
27using HTMLDocument document = new HTMLDocument("zip-file:///test.html", configuration);
28
29// Create the PDF Device
30using PdfDevice device = new PdfDevice(savePath);
31
32// Render ZIP to PDF
33document.RenderTo(device);The Configuration() constructor creates an instance of the
Configuration class. After the configuration is created, the GetService<INetworkService>(), MessageHandlers.Add(), and MessageHandlers.Insert() methods are invoked. Insert() places a handler at a specific position in the collection; Add() appends a handler to the end. The figure shows the chain of message handlers for this example:

Note: The HTMLDocument(address, configuration) constructor takes the absolute path to the ZIP archive. Related resources can still use paths relative to the HTML document inside the archive, as shown in the example.
You can download the complete examples and data files from GitHub.
The start handler records the beginning of request processing, and the stop handler records the end. Their positions in the pipeline define what part of the workflow is measured.
It measures the request execution path handled by the configured message handlers while the HTML document is loaded and rendered to PDF.
Yes. Message handlers are designed as a pipeline, so logging can be combined with ZIP resource resolution, authentication, request filtering, and timeout handling.
Analyzing your prompt, please hold on...
An error occurred while retrieving the results. Please refresh the page and try again.