diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json
index 6732295..2e5b1c3 100644
--- a/.config/dotnet-tools.json
+++ b/.config/dotnet-tools.json
@@ -3,7 +3,7 @@
"isRoot": true,
"tools": {
"csharpier": {
- "version": "0.29.1",
+ "version": "0.30.1",
"commands": [
"dotnet-csharpier"
],
diff --git a/.editorconfig b/.editorconfig
index 3f80c7c..0d2cc07 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -16,3 +16,10 @@ insert_final_newline = true
[*.md]
trim_trailing_whitespace = false
+
+[*.{cs,vb}]
+csharp_style_namespace_declarations = file_scoped
+csharp_style_var_for_built_in_types = true
+csharp_style_var_elsewhere = true
+
+
diff --git a/.github/workflows/build-on-pull-request.yml b/.github/workflows/build-on-pull-request.yml
index 81a7618..ac31d3e 100644
--- a/.github/workflows/build-on-pull-request.yml
+++ b/.github/workflows/build-on-pull-request.yml
@@ -16,7 +16,7 @@ jobs:
- name: Setup dotnet
uses: actions/setup-dotnet@v4
with:
- dotnet-version: '8.x'
+ dotnet-version: '9.x'
- name: Restore dotnet tools
run: dotnet tool restore
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
index a33b8a4..e70ac46 100644
--- a/.github/workflows/codeql.yml
+++ b/.github/workflows/codeql.yml
@@ -41,7 +41,7 @@ jobs:
steps:
- name: Checkout repository
- uses: actions/checkout@v3
+ uses: actions/checkout@main
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
@@ -57,9 +57,9 @@ jobs:
- name: Setup dotnet
- uses: actions/setup-dotnet@v3
+ uses: actions/setup-dotnet@v4
with:
- dotnet-version: '8.x'
+ dotnet-version: '9.x'
- name: Build with dotnet
run: dotnet build --configuration Release
diff --git a/.github/workflows/main-deploy-nuget.yml b/.github/workflows/main-deploy-nuget.yml
index 8c67cfa..e0b8b9e 100644
--- a/.github/workflows/main-deploy-nuget.yml
+++ b/.github/workflows/main-deploy-nuget.yml
@@ -14,7 +14,7 @@ jobs:
- name: Setup dotnet
uses: actions/setup-dotnet@v4
with:
- dotnet-version: '8.x'
+ dotnet-version: '9.x'
- name: Package BlazorReports
run: dotnet pack src/BlazorReports
diff --git a/BlazorReports.sln b/BlazorReports.sln
index 920a23a..fb6f2d8 100644
--- a/BlazorReports.sln
+++ b/BlazorReports.sln
@@ -16,6 +16,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "examples", "examples", "{C5
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleReportServer", "examples\SimpleReportServer\SimpleReportServer.csproj", "{1C60A5A2-46DB-419D-BED1-5C97465076D0}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExampleTemplates", "examples\ExampleTemplates\ExampleTemplates.csproj", "{B0C3AFB8-AA52-4947-863F-9DEEC9D889AE}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -42,6 +44,10 @@ Global
{1C60A5A2-46DB-419D-BED1-5C97465076D0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1C60A5A2-46DB-419D-BED1-5C97465076D0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1C60A5A2-46DB-419D-BED1-5C97465076D0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B0C3AFB8-AA52-4947-863F-9DEEC9D889AE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B0C3AFB8-AA52-4947-863F-9DEEC9D889AE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B0C3AFB8-AA52-4947-863F-9DEEC9D889AE}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B0C3AFB8-AA52-4947-863F-9DEEC9D889AE}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{2AA5462E-57F7-4A4B-A1BB-1BFF901A7C22} = {84E7AF5B-BDD3-4FB3-A798-7E8541EE7A1E}
@@ -49,5 +55,6 @@ Global
{DAF00FAE-4B76-4FA6-9690-14F12DB123DB} = {84E7AF5B-BDD3-4FB3-A798-7E8541EE7A1E}
{35F37EF3-9BFD-4C4A-ACDA-761D62E3E940} = {84E7AF5B-BDD3-4FB3-A798-7E8541EE7A1E}
{1C60A5A2-46DB-419D-BED1-5C97465076D0} = {C5BFD20E-2F4E-4EA8-AC79-82E91F93E70F}
+ {B0C3AFB8-AA52-4947-863F-9DEEC9D889AE} = {C5BFD20E-2F4E-4EA8-AC79-82E91F93E70F}
EndGlobalSection
EndGlobal
diff --git a/examples/ExampleTemplates/Components/ExampleHeader.razor b/examples/ExampleTemplates/Components/ExampleHeader.razor
new file mode 100644
index 0000000..c9051cb
--- /dev/null
+++ b/examples/ExampleTemplates/Components/ExampleHeader.razor
@@ -0,0 +1,7 @@
+
+
Testing Header
+
+
+@code {
+
+}
diff --git a/examples/ExampleTemplates/ExampleTemplates.csproj b/examples/ExampleTemplates/ExampleTemplates.csproj
new file mode 100644
index 0000000..12d8ada
--- /dev/null
+++ b/examples/ExampleTemplates/ExampleTemplates.csproj
@@ -0,0 +1,17 @@
+
+
+
+ net9.0
+ true
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/ExampleTemplates/Reports/ReportWithRepeatingHeaderPerPage.razor b/examples/ExampleTemplates/Reports/ReportWithRepeatingHeaderPerPage.razor
new file mode 100644
index 0000000..a27e99b
--- /dev/null
+++ b/examples/ExampleTemplates/Reports/ReportWithRepeatingHeaderPerPage.razor
@@ -0,0 +1,50 @@
+@* This component will render a repeating header on each page when printed *@
+
+@* This component will render a repeating header on each page when printed *@
+
+
+
+
+
+ @for (int i = 0; i < 100; i++)
+ {
+
This is line number @i
+ }
+
+
+
+
+
+@code {
+
+}
diff --git a/examples/ExampleTemplates/_Imports.razor b/examples/ExampleTemplates/_Imports.razor
new file mode 100644
index 0000000..7728512
--- /dev/null
+++ b/examples/ExampleTemplates/_Imports.razor
@@ -0,0 +1 @@
+@using Microsoft.AspNetCore.Components.Web
diff --git a/examples/ExampleTemplates/wwwroot/background.png b/examples/ExampleTemplates/wwwroot/background.png
new file mode 100644
index 0000000..e15a3bd
Binary files /dev/null and b/examples/ExampleTemplates/wwwroot/background.png differ
diff --git a/examples/ExampleTemplates/wwwroot/exampleJsInterop.js b/examples/ExampleTemplates/wwwroot/exampleJsInterop.js
new file mode 100644
index 0000000..ea8d76a
--- /dev/null
+++ b/examples/ExampleTemplates/wwwroot/exampleJsInterop.js
@@ -0,0 +1,6 @@
+// This is a JavaScript module that is loaded on demand. It can export any number of
+// functions, and may import other JavaScript modules if required.
+
+export function showPrompt(message) {
+ return prompt(message, 'Type anything here');
+}
diff --git a/examples/SimpleReportServer/Program.cs b/examples/SimpleReportServer/Program.cs
index 17a379b..d4eaaa8 100644
--- a/examples/SimpleReportServer/Program.cs
+++ b/examples/SimpleReportServer/Program.cs
@@ -1,12 +1,16 @@
using BlazorReports.Extensions;
using BlazorReports.Models;
+using ExampleTemplates.Reports;
using SimpleReportServer;
var builder = WebApplication.CreateSlimBuilder(args);
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
-builder.Services.AddBlazorReports();
+builder.Services.AddBlazorReports(opts =>
+{
+ opts.BrowserOptions.ResponseTimeout = TimeSpan.FromSeconds(90);
+});
var app = builder.Build();
@@ -16,12 +20,17 @@
app.UseSwaggerUI();
}
-app.MapGroup("reports").MapBlazorReport();
-app.MapGroup("reports")
- .MapBlazorReport(opts =>
- {
- opts.ReportName = "HelloReportHtml";
- opts.OutputFormat = ReportOutputFormat.Html;
- });
+var reportsGroup = app.MapGroup("reports");
+
+reportsGroup.MapBlazorReport();
+reportsGroup.MapBlazorReport(opts =>
+{
+ opts.ReportName = "HelloReportHtml";
+ opts.OutputFormat = ReportOutputFormat.Html;
+});
+reportsGroup.MapBlazorReport(opts =>
+{
+ opts.OutputFormat = ReportOutputFormat.Pdf;
+});
app.Run();
diff --git a/examples/SimpleReportServer/SimpleReportServer.csproj b/examples/SimpleReportServer/SimpleReportServer.csproj
index 4d5d235..20323c7 100644
--- a/examples/SimpleReportServer/SimpleReportServer.csproj
+++ b/examples/SimpleReportServer/SimpleReportServer.csproj
@@ -1,16 +1,19 @@
- net8.0
+ net9.0
+ true
+ $(NoWarn);CS1591
-
-
+
+
+
diff --git a/src/BlazorReports.Client/BlazorReports.Client.csproj b/src/BlazorReports.Client/BlazorReports.Client.csproj
index 292a753..9a1b332 100644
--- a/src/BlazorReports.Client/BlazorReports.Client.csproj
+++ b/src/BlazorReports.Client/BlazorReports.Client.csproj
@@ -1,14 +1,12 @@
-
- net6.0
- enable
- enable
-
+
+ net8.0
+
-
-
-
-
-
+
+
+
+
+
diff --git a/src/BlazorReports.Components/BlazorReports.Components.csproj b/src/BlazorReports.Components/BlazorReports.Components.csproj
index 89c122a..1e41b8c 100644
--- a/src/BlazorReports.Components/BlazorReports.Components.csproj
+++ b/src/BlazorReports.Components/BlazorReports.Components.csproj
@@ -1,34 +1,27 @@
- net6.0;net7.0;net8.0
- enable
- enable
+ net8.0;net9.0
true
- true
$(NoWarn);NU5104
Blazor Reports Components
Blazor components for BlazorReports. Generate PDF reports using Blazor Components. Easily create a report server or generate reports from existing projects.
-
+
-
+
-
-
-
-
-
-
+
+
-
-
+
+
diff --git a/src/BlazorReports.Viewer/BlazorReports.Viewer.csproj b/src/BlazorReports.Viewer/BlazorReports.Viewer.csproj
index c46ef51..308f30e 100644
--- a/src/BlazorReports.Viewer/BlazorReports.Viewer.csproj
+++ b/src/BlazorReports.Viewer/BlazorReports.Viewer.csproj
@@ -2,8 +2,6 @@
net8.0
- enable
- enable
diff --git a/src/BlazorReports/BlazorReports.csproj b/src/BlazorReports/BlazorReports.csproj
index 9900985..6939b4c 100644
--- a/src/BlazorReports/BlazorReports.csproj
+++ b/src/BlazorReports/BlazorReports.csproj
@@ -1,9 +1,7 @@
- net8.0
- enable
- enable
+ net8.0;net9.0
true
Blazor Reports
Generate PDF reports using Blazor Components. Easily create a report server or generate reports from existing projects.
@@ -19,7 +17,7 @@
-
+
diff --git a/src/BlazorReports/Extensions/ReportExtensions.cs b/src/BlazorReports/Extensions/ReportExtensions.cs
index 44078b2..3d360a6 100644
--- a/src/BlazorReports/Extensions/ReportExtensions.cs
+++ b/src/BlazorReports/Extensions/ReportExtensions.cs
@@ -193,7 +193,7 @@ private static BlazorReportRegistrationOptions GetReportRegistrationOptions(
Action? setupAction = null
)
{
- var options = new BlazorReportRegistrationOptions();
+ BlazorReportRegistrationOptions options = new();
var globalOptions = serviceScope
.ServiceProvider.GetRequiredService>()
.Value;
diff --git a/src/BlazorReports/Helpers/MimeTypes.cs b/src/BlazorReports/Helpers/MimeTypes.cs
index 9eb14c7..7601e0f 100644
--- a/src/BlazorReports/Helpers/MimeTypes.cs
+++ b/src/BlazorReports/Helpers/MimeTypes.cs
@@ -5,18 +5,17 @@
///
internal static class MimeTypes
{
- private static readonly Dictionary MimeTypesDictionary =
- new()
- {
- { ".txt", "text/plain" },
- { ".pdf", "application/pdf" },
- { ".csv", "text/csv" },
- { ".png", "image/png" },
- { ".jpg", "image/jpeg" },
- { ".jpeg", "image/jpeg" },
- { ".gif", "image/gif" },
- { ".webp", "image/webp" },
- };
+ private static readonly Dictionary MimeTypesDictionary = new()
+ {
+ { ".txt", "text/plain" },
+ { ".pdf", "application/pdf" },
+ { ".csv", "text/csv" },
+ { ".png", "image/png" },
+ { ".jpg", "image/jpeg" },
+ { ".jpeg", "image/jpeg" },
+ { ".gif", "image/gif" },
+ { ".webp", "image/webp" },
+ };
private const string UnknownMimeType = "application/octet-stream";
@@ -30,16 +29,8 @@ public static string GetMimeType(string fileName)
{
var extension = Path.GetExtension(fileName).ToLowerInvariant();
- if (string.IsNullOrEmpty(extension))
- {
- return UnknownMimeType;
- }
-
- if (!MimeTypesDictionary.TryGetValue(extension, out var mimeType))
- {
- return UnknownMimeType;
- }
-
- return mimeType;
+ return string.IsNullOrEmpty(extension)
+ ? UnknownMimeType
+ : MimeTypesDictionary.GetValueOrDefault(extension, UnknownMimeType);
}
}
diff --git a/src/BlazorReports/Models/BlazorReportRegistry.cs b/src/BlazorReports/Models/BlazorReportRegistry.cs
index 012b5b9..fec0360 100644
--- a/src/BlazorReports/Models/BlazorReportRegistry.cs
+++ b/src/BlazorReports/Models/BlazorReportRegistry.cs
@@ -22,7 +22,7 @@ public BlazorReportRegistry(IOptions options)
if (!string.IsNullOrWhiteSpace(options.Value.AssetsPath))
{
var assetsPath = options.Value.AssetsPath;
- var assetsDirectory = new DirectoryInfo(assetsPath);
+ DirectoryInfo assetsDirectory = new(assetsPath);
if (assetsDirectory.Exists)
{
foreach (var file in assetsDirectory.GetFiles())
@@ -51,12 +51,12 @@ public BlazorReportRegistry(IOptions options)
///
/// The global assets for the BlazorReportRegistry.
///
- public Dictionary GlobalAssets { get; set; } = new();
+ public Dictionary GlobalAssets { get; set; } = [];
///
/// The BlazorReport objects for the BlazorReportRegistry.
///
- public Dictionary Reports { get; } = new();
+ public Dictionary Reports { get; } = [];
///
/// Adds a report to the BlazorReportRegistry.
@@ -71,10 +71,13 @@ public BlazorReport AddReport(BlazorReportRegistrationOptions? options = null
var normalizedReportName = reportNameToUse.ToLowerInvariant().Trim();
if (Reports.ContainsKey(normalizedReportName))
+ {
throw new InvalidOperationException(
$"Report with name {normalizedReportName} already exists"
);
- var blazorReport = new BlazorReport
+ }
+
+ BlazorReport blazorReport = new()
{
OutputFormat = options?.OutputFormat ?? ReportOutputFormat.Pdf,
Name = reportNameToUse,
@@ -90,7 +93,7 @@ public BlazorReport AddReport(BlazorReportRegistrationOptions? options = null
if (!string.IsNullOrEmpty(options?.AssetsPath))
{
var assetsPath = options.AssetsPath;
- var assetsDirectory = new DirectoryInfo(assetsPath);
+ DirectoryInfo assetsDirectory = new(assetsPath);
if (assetsDirectory.Exists)
{
foreach (var file in assetsDirectory.GetFiles())
@@ -120,10 +123,13 @@ public BlazorReport AddReport(BlazorReportRegistrationOptions? options =
var normalizedReportName = reportNameToUse.ToLowerInvariant().Trim();
if (Reports.ContainsKey(normalizedReportName))
+ {
throw new InvalidOperationException(
$"Report with name {normalizedReportName} already exists"
);
- var blazorReport = new BlazorReport
+ }
+
+ BlazorReport blazorReport = new()
{
OutputFormat = options?.OutputFormat ?? ReportOutputFormat.Pdf,
Name = reportNameToUse,
@@ -139,7 +145,7 @@ public BlazorReport AddReport(BlazorReportRegistrationOptions? options =
if (!string.IsNullOrEmpty(options?.AssetsPath))
{
var assetsPath = options.AssetsPath;
- var assetsDirectory = new DirectoryInfo(assetsPath);
+ DirectoryInfo assetsDirectory = new(assetsPath);
if (assetsDirectory.Exists)
{
foreach (var file in assetsDirectory.GetFiles())
diff --git a/src/BlazorReports/Services/BrowserServices/Browser.cs b/src/BlazorReports/Services/BrowserServices/Browser.cs
index afcf6f3..ed94142 100644
--- a/src/BlazorReports/Services/BrowserServices/Browser.cs
+++ b/src/BlazorReports/Services/BrowserServices/Browser.cs
@@ -79,7 +79,9 @@ out browserPage
}
if (operationCancelled)
+ {
return new OperationCancelledProblem();
+ }
if (retryCount >= maxRetryCount)
{
@@ -108,7 +110,9 @@ out browserPage
finally
{
if (browserPage is not null && !browserPagedDisposed)
+ {
ReturnBrowserPage(browserPage);
+ }
}
return new Success();
@@ -169,11 +173,14 @@ private async ValueTask DisposeBrowserPage(BrowserPage browserPage)
try
{
if (_browserPagePool.Contains(browserPage))
+ {
return;
+ }
+
await browserPage.DisposeAsync();
_currentBrowserPagePoolSize--;
- var closeTargetMessage = new BrowserMessage("Target.closeTarget");
+ BrowserMessage closeTargetMessage = new("Target.closeTarget");
closeTargetMessage.Parameters.Add("targetId", browserPage.TargetId);
await connection.ConnectAsync();
connection.SendAsync(closeTargetMessage);
@@ -191,7 +198,7 @@ private async ValueTask DisposeBrowserPage(BrowserPage browserPage)
/// The browser page
private async ValueTask CreateBrowserPage(CancellationToken stoppingToken = default)
{
- var createTargetMessage = new BrowserMessage("Target.createTarget");
+ BrowserMessage createTargetMessage = new("Target.createTarget");
createTargetMessage.Parameters.Add("url", "about:blank");
await connection.ConnectAsync(stoppingToken);
return await connection.SendAsync(
@@ -220,11 +227,16 @@ public async ValueTask DisposeAsync()
LogMessages.BrowserDispose(logger, chromiumProcess.Id);
_poolLock.Dispose();
foreach (var browserPage in _browserPagePool)
+ {
await browserPage.DisposeAsync();
+ }
+
chromiumProcess.Kill();
chromiumProcess.Dispose();
await connection.DisposeAsync();
if (dataDirectory.Exists)
+ {
Directory.Delete(dataDirectory.FullName, true);
+ }
}
}
diff --git a/src/BlazorReports/Services/BrowserServices/BrowserPage.cs b/src/BlazorReports/Services/BrowserServices/BrowserPage.cs
index 322978f..e2df393 100644
--- a/src/BlazorReports/Services/BrowserServices/BrowserPage.cs
+++ b/src/BlazorReports/Services/BrowserServices/BrowserPage.cs
@@ -30,8 +30,9 @@ Connection connection
/// The id of the page in the browser
///
internal readonly string TargetId = targetId;
- private readonly CustomFromBase64Transform _transform =
- new(FromBase64TransformMode.IgnoreWhiteSpaces);
+ private readonly CustomFromBase64Transform _transform = new(
+ FromBase64TransformMode.IgnoreWhiteSpaces
+ );
///
/// Displays the HTML in the browser
@@ -43,14 +44,16 @@ internal async Task DisplayHtml(string html, CancellationToken stoppingToken = d
{
await connection.ConnectAsync(stoppingToken);
if (string.IsNullOrWhiteSpace(html))
+ {
throw new ArgumentException("Value cannot be null or whitespace.", nameof(html));
+ }
// Enables or disables the cache
- var cacheMessage = new BrowserMessage("Network.setCacheDisabled");
+ BrowserMessage cacheMessage = new("Network.setCacheDisabled");
cacheMessage.Parameters.Add("cacheDisabled", false);
connection.SendAsync(cacheMessage);
- var getPageFrameTreeMessage = new BrowserMessage("Page.getFrameTree");
+ BrowserMessage getPageFrameTreeMessage = new("Page.getFrameTree");
await connection.SendAsync(
getPageFrameTreeMessage,
PageGetFrameTreeResponseSerializationContext
@@ -58,7 +61,7 @@ await connection.SendAsync(
.BrowserResultResponsePageGetFrameTreeResponse,
response =>
{
- var pageSetDocumentContentMessage = new BrowserMessage("Page.setDocumentContent");
+ BrowserMessage pageSetDocumentContentMessage = new("Page.setDocumentContent");
pageSetDocumentContentMessage.Parameters.Add("frameId", response.Result.FrameTree.Frame.Id);
pageSetDocumentContentMessage.Parameters.Add("html", html);
connection.SendAsync(pageSetDocumentContentMessage);
@@ -84,9 +87,11 @@ await connection.SendAsync(
async pagePrintToPdfResponse =>
{
if (string.IsNullOrEmpty(pagePrintToPdfResponse.Result.Stream))
+ {
return;
+ }
- var ioReadMessage = new BrowserMessage("IO.read");
+ BrowserMessage ioReadMessage = new("IO.read");
ioReadMessage.Parameters.Add("handle", pagePrintToPdfResponse.Result.Stream);
ioReadMessage.Parameters.Add("size", 50 * 1024);
@@ -94,7 +99,10 @@ await connection.SendAsync(
while (true)
{
if (finished)
+ {
break;
+ }
+
await connection.SendAsync(
ioReadMessage,
IoReadResponseSerializationContext.Default.BrowserResultResponseIoReadResponse,
@@ -128,7 +136,7 @@ private static BrowserMessage CreatePrintToPdfBrowserMessage(
BlazorReportsPageSettings pageSettings
)
{
- var message = new BrowserMessage("Page.printToPDF");
+ BrowserMessage message = new("Page.printToPDF");
message.Parameters.Add(
"landscape",
pageSettings.Orientation == BlazorReportsPageOrientation.Landscape
@@ -140,6 +148,45 @@ BlazorReportsPageSettings pageSettings
message.Parameters.Add("marginLeft", pageSettings.MarginLeft);
message.Parameters.Add("marginRight", pageSettings.MarginRight);
message.Parameters.Add("printBackground", !pageSettings.IgnoreBackground);
+ message.Parameters.Add("displayHeaderFooter", true);
+ message.Parameters.Add(
+ "headerTemplate",
+ """
+
+
+
+ """
+ // """
+ //
+ // """
+ );
message.Parameters.Add("transferMode", "ReturnAsStream");
return message;
@@ -152,7 +199,10 @@ CancellationToken stoppingToken
)
{
if (data.Length == 0)
+ {
return;
+ }
+
var sharedPool = ArrayPool.Shared;
var dataBytes = sharedPool.Rent(data.Length);
var inputBlock = sharedPool.Rent(CustomFromBase64Transform.InputBlockSize);
@@ -181,7 +231,10 @@ CancellationToken stoppingToken
writer.Advance(count);
var flushResult = await writer.FlushAsync(stoppingToken);
if (flushResult.IsCanceled || flushResult.IsCompleted)
+ {
break;
+ }
+
writerBuffer = writer.GetMemory(count); // Get a new buffer after advancing
}
}
@@ -196,7 +249,7 @@ CancellationToken stoppingToken
private async ValueTask ClosePdfStream(string stream, CancellationToken stoppingToken = default)
{
await connection.ConnectAsync(stoppingToken);
- var ioCloseMessage = new BrowserMessage("IO.close");
+ BrowserMessage ioCloseMessage = new("IO.close");
ioCloseMessage.Parameters.Add("handle", stream);
connection.SendAsync(ioCloseMessage);
}
diff --git a/src/BlazorReports/Services/BrowserServices/BrowserService.cs b/src/BlazorReports/Services/BrowserServices/BrowserService.cs
index 83cf6ee..39f3ade 100644
--- a/src/BlazorReports/Services/BrowserServices/BrowserService.cs
+++ b/src/BlazorReports/Services/BrowserServices/BrowserService.cs
@@ -159,6 +159,8 @@ public async ValueTask DisposeAsync()
_browserPoolLock.Dispose();
_browserStartLock.Dispose();
while (_browserQueue.TryDequeue(out var browser))
+ {
await browser.DisposeAsync();
+ }
}
}
diff --git a/src/BlazorReports/Services/BrowserServices/Connection.cs b/src/BlazorReports/Services/BrowserServices/Connection.cs
index e582c33..9f6325d 100644
--- a/src/BlazorReports/Services/BrowserServices/Connection.cs
+++ b/src/BlazorReports/Services/BrowserServices/Connection.cs
@@ -15,7 +15,14 @@ namespace BlazorReports.Services.BrowserServices;
///
/// Represents a connection to the browser
///
-internal sealed class Connection : IAsyncDisposable
+///
+/// The constructor of the connection
+///
+/// The uri of the connection
+/// The response timeout
+/// The logger
+internal sealed class Connection(Uri uri, TimeSpan responseTimeout, ILogger logger)
+ : IAsyncDisposable
{
private ClientWebSocket _webSocket = new();
private readonly ArrayPool _bufferPool = ArrayPool.Shared;
@@ -29,26 +36,11 @@ internal sealed class Connection : IAsyncDisposable
private Task? _receiveTask;
private readonly SemaphoreSlim _connectionLock = new(1, 1);
private readonly CancellationTokenSource _cts = new();
- private readonly TimeSpan _responseTimeout;
- private readonly ILogger _logger;
///
/// The uri of the connection
///
- public readonly Uri Uri;
-
- ///
- /// The constructor of the connection
- ///
- /// The uri of the connection
- /// The response timeout
- /// The logger
- public Connection(Uri uri, TimeSpan responseTimeout, ILogger logger)
- {
- Uri = uri;
- _responseTimeout = responseTimeout;
- _logger = logger;
- }
+ public readonly Uri Uri = uri;
public async Task InitializeAsync(CancellationToken stoppingToken = default)
{
@@ -56,7 +48,9 @@ public async Task InitializeAsync(CancellationToken stoppingToken = default)
try
{
if (_webSocket.State is not WebSocketState.None)
+ {
return;
+ }
await _webSocket.ConnectAsync(Uri, stoppingToken);
@@ -80,7 +74,9 @@ public async ValueTask> ConnectAsync(
)
{
if (_webSocket.State is WebSocketState.Open)
+ {
return new Success();
+ }
await _connectionLock.WaitAsync(stoppingToken);
@@ -102,13 +98,15 @@ public async ValueTask> ConnectAsync(
retries--; // decrease remaining retries
if (retries > 0) // don't delay if no more retries left
+ {
await Task.Delay(TimeSpan.FromSeconds(3), stoppingToken); // wait for 3 seconds before next attempt
+ }
}
}
if (_webSocket.State is not WebSocketState.Open)
{
- LogMessages.UnableToEstablishWebSocketConnection(_logger, Uri);
+ LogMessages.UnableToEstablishWebSocketConnection(logger, Uri);
return new ConnectionProblem();
}
@@ -130,14 +128,16 @@ private async Task ProcessSendQueueAsync()
await _sendSignal.WaitAsync(_cts.Token);
if (!_sendQueue.TryDequeue(out var message))
+ {
continue;
+ }
var buffer = JsonSerializer.SerializeToUtf8Bytes(
message,
BrowserMessageSerializationContext.Default.BrowserMessage
);
bufferToSend = _bufferPool.Rent(buffer.Length);
- var bufferToSendMemory = new Memory(bufferToSend);
+ Memory bufferToSendMemory = new(bufferToSend);
buffer.CopyTo(bufferToSendMemory);
await _webSocket.SendAsync(
bufferToSendMemory[..buffer.Length],
@@ -149,19 +149,21 @@ await _webSocket.SendAsync(
}
catch (OperationCanceledException)
{
- LogMessages.SendQueueProcessingCancelled(_logger, Uri);
+ LogMessages.SendQueueProcessingCancelled(logger, Uri);
}
finally
{
if (bufferToSend is not null)
+ {
_bufferPool.Return(bufferToSend);
+ }
}
}
private async Task ProcessResponsesAsync()
{
var bufferToReceive = _bufferPool.Rent(BufferSize);
- var bufferToReceiveMemory = new Memory(bufferToReceive);
+ Memory bufferToReceiveMemory = new(bufferToReceive);
try
{
@@ -170,10 +172,12 @@ private async Task ProcessResponsesAsync()
var result = await _webSocket.ReceiveAsync(bufferToReceiveMemory, _cts.Token);
var messageReceived = bufferToReceiveMemory[..result.Count];
- var jsonDoc = JsonDocument.Parse(messageReceived);
+ JsonDocument jsonDoc = JsonDocument.Parse(messageReceived);
var root = jsonDoc.RootElement;
if (!root.TryGetProperty("id", out var methodElement))
+ {
continue;
+ }
var id = methodElement.GetInt32();
@@ -185,7 +189,7 @@ private async Task ProcessResponsesAsync()
}
catch (OperationCanceledException)
{
- LogMessages.ReceiveQueueProcessingCancelled(_logger, Uri);
+ LogMessages.ReceiveQueueProcessingCancelled(logger, Uri);
}
catch (WebSocketException)
{
@@ -193,7 +197,7 @@ private async Task ProcessResponsesAsync()
}
catch (Exception ex)
{
- LogMessages.ReceiveQueueProcessingError(_logger, ex, Uri);
+ LogMessages.ReceiveQueueProcessingError(logger, ex, Uri);
}
finally
{
@@ -210,11 +214,13 @@ CancellationToken stoppingToken
_sendQueue.Enqueue(message);
_sendSignal.Release();
- var tcs = new TaskCompletionSource();
+ TaskCompletionSource tcs = new();
_responseTasks[message.Id] = tcs;
- using var timeoutCts = CancellationTokenSource.CreateLinkedTokenSource(stoppingToken);
- timeoutCts.CancelAfter(_responseTimeout);
+ using CancellationTokenSource timeoutCts = CancellationTokenSource.CreateLinkedTokenSource(
+ stoppingToken
+ );
+ timeoutCts.CancelAfter(responseTimeout);
if (await Task.WhenAny(tcs.Task, Task.Delay(-1, timeoutCts.Token)) == tcs.Task)
{
@@ -236,10 +242,9 @@ public async ValueTask SendAsync(
var response = await SendMessageAsync(message, stoppingToken);
var parsedMessage = response.RootElement.Deserialize(returnDataJsonTypeInfo);
- if (parsedMessage is null)
- throw new JsonException("Could not deserialize response");
-
- return parsedMessage;
+ return parsedMessage is null
+ ? throw new JsonException("Could not deserialize response")
+ : parsedMessage;
}
///
@@ -259,10 +264,9 @@ public async ValueTask SendAsync(
var response = await SendMessageAsync(message, stoppingToken);
var parsedMessage = response.RootElement.Deserialize(returnDataJsonTypeInfo);
- if (parsedMessage is null)
- throw new JsonException("Could not deserialize response");
-
- return await responseHandler(parsedMessage);
+ return parsedMessage is null
+ ? throw new JsonException("Could not deserialize response")
+ : await responseHandler(parsedMessage);
}
///
@@ -280,11 +284,9 @@ public async ValueTask SendAsync(
)
{
var response = await SendMessageAsync(message, stoppingToken);
- var parsedMessage = response.RootElement.Deserialize(returnDataJsonTypeInfo);
-
- if (parsedMessage is null)
- throw new JsonException("Could not deserialize response");
-
+ var parsedMessage =
+ response.RootElement.Deserialize(returnDataJsonTypeInfo)
+ ?? throw new JsonException("Could not deserialize response");
responseAction(parsedMessage);
}
@@ -306,17 +308,15 @@ public async ValueTask SendAsync(
_sendQueue.Enqueue(message);
_sendSignal.Release();
- var tcs = new TaskCompletionSource();
+ TaskCompletionSource tcs = new();
_responseTasks[message.Id] = tcs;
- if (await Task.WhenAny(tcs.Task, Task.Delay(_responseTimeout, stoppingToken)) == tcs.Task)
+ if (await Task.WhenAny(tcs.Task, Task.Delay(responseTimeout, stoppingToken)) == tcs.Task)
{
var response = await tcs.Task;
- var parsedMessage = response.RootElement.Deserialize(returnDataJsonTypeInfo);
-
- if (parsedMessage is null)
- throw new JsonException("Could not deserialize response");
-
+ var parsedMessage =
+ response.RootElement.Deserialize(returnDataJsonTypeInfo)
+ ?? throw new JsonException("Could not deserialize response");
await responseAction(parsedMessage);
}
else
@@ -340,9 +340,14 @@ public async ValueTask DisposeAsync()
await _cts.CancelAsync();
if (_sendTask is not null)
+ {
await _sendTask;
+ }
+
if (_receiveTask is not null)
+ {
await _receiveTask;
+ }
_webSocket.Dispose();
_sendSignal.Dispose();
diff --git a/src/BlazorReports/Services/BrowserServices/CustomFromBase64Transform.cs b/src/BlazorReports/Services/BrowserServices/CustomFromBase64Transform.cs
index b226aa9..4896695 100644
--- a/src/BlazorReports/Services/BrowserServices/CustomFromBase64Transform.cs
+++ b/src/BlazorReports/Services/BrowserServices/CustomFromBase64Transform.cs
@@ -54,7 +54,7 @@ int outputOffset
return 0;
}
- ConvertFromBase64(transformBuffer, outputBuffer[outputOffset..], out int written);
+ ConvertFromBase64(transformBuffer, outputBuffer[outputOffset..], out var written);
ReturnToCryptoPool(transformBufferArray, transformBuffer.Length);
@@ -175,7 +175,10 @@ internal static class CryptoPool
{
private const int ClearAll = -1;
- internal static byte[] Rent(int minimumLength) => ArrayPool.Shared.Rent(minimumLength);
+ internal static byte[] Rent(int minimumLength)
+ {
+ return ArrayPool.Shared.Rent(minimumLength);
+ }
internal static void Return(byte[] array, int clearSize = ClearAll)
{
diff --git a/src/BlazorReports/Services/BrowserServices/Factories/BrowserFactory.cs b/src/BlazorReports/Services/BrowserServices/Factories/BrowserFactory.cs
index cd6e302..0e97f65 100644
--- a/src/BlazorReports/Services/BrowserServices/Factories/BrowserFactory.cs
+++ b/src/BlazorReports/Services/BrowserServices/Factories/BrowserFactory.cs
@@ -36,18 +36,22 @@ public async ValueTask> CreateBrowser()
: BrowserFinder.Find(browserOptions.Browser);
if (!File.Exists(browserExecutableLocation))
+ {
throw new FileNotFoundException(
$"Could not find browser in location '{browserExecutableLocation}'"
);
+ }
var temporaryPath = Path.GetTempPath();
var devToolsDirectory = Path.Combine(temporaryPath, Guid.NewGuid().ToString());
Directory.CreateDirectory(devToolsDirectory);
- var devToolsActivePortDirectory = new DirectoryInfo(devToolsDirectory);
+ DirectoryInfo devToolsActivePortDirectory = new(devToolsDirectory);
var devToolsActivePortFile = Path.Combine(devToolsDirectory, "DevToolsActivePort");
if (File.Exists(devToolsActivePortFile))
+ {
File.Delete(devToolsActivePortFile);
+ }
var chromiumProcess = CreateChromiumProcess(
browserExecutableLocation,
@@ -82,7 +86,7 @@ public async ValueTask> CreateBrowser()
LogMessages.BrowserDataDirectoryUsed(browserFactoryLogger, devToolsDirectory);
- var uri = new Uri($"ws://127.0.0.1:{lines[0]}{lines[1]}");
+ Uri uri = new($"ws://127.0.0.1:{lines[0]}{lines[1]}");
var connection = await connectionFactory.CreateConnection(uri, browserOptions.ResponseTimeout);
return new Browser(
chromiumProcess,
@@ -107,9 +111,9 @@ private Process CreateChromiumProcess(
BlazorReportsBrowserOptions browserOptions
)
{
- var chromiumProcess = new Process();
- var defaultChromiumArgument = new List
- {
+ Process chromiumProcess = new();
+ List defaultChromiumArgument =
+ [
"--headless=new",
"--disable-gpu",
"--hide-scrollbars",
@@ -127,18 +131,22 @@ BlazorReportsBrowserOptions browserOptions
"--disable-crash-reporter",
"--remote-debugging-port=\"0\"",
$"--user-data-dir=\"{devToolsDirectory}\"",
- };
+ ];
if (browserOptions.NoSandbox)
+ {
defaultChromiumArgument.Add("--no-sandbox");
+ }
if (browserOptions.DisableDevShmUsage)
+ {
defaultChromiumArgument.Add("--disable-dev-shm-usage");
+ }
var chromiumArguments = string.Join(" ", defaultChromiumArgument);
LogMessages.StartingChromiumProcess(browserFactoryLogger, chromiumArguments);
- var processStartInfo = new ProcessStartInfo
+ ProcessStartInfo processStartInfo = new()
{
FileName = chromiumExeFileName,
Arguments = chromiumArguments,
@@ -159,9 +167,14 @@ private void ChromiumProcess_Exited(object? sender, EventArgs e)
{
// Log errors with details
if (sender is not Process process)
+ {
return;
+ }
+
if (process.ExitCode == 0)
+ {
return;
+ }
var exception = Marshal.GetExceptionForHR(process.ExitCode);
LogMessages.ChromiumProcessCrashed(browserFactoryLogger, exception, process.ExitCode);
@@ -173,22 +186,27 @@ DirectoryInfo devToolsActivePortDirectory
)
{
if (devToolsActivePortDirectory is null || !devToolsActivePortDirectory.Exists)
+ {
throw new DirectoryNotFoundException($"The {nameof(devToolsActivePortDirectory)} is null");
+ }
- var watcher = new FileSystemWatcher
+ FileSystemWatcher watcher = new()
{
Path = devToolsActivePortDirectory.FullName,
Filter = Path.GetFileName(devToolsActivePortFile),
EnableRaisingEvents = true,
};
- var cts = new CancellationTokenSource(TimeSpan.FromSeconds(10)); // 10 second timeout
- var tcs = new TaskCompletionSource();
+ CancellationTokenSource cts = new(TimeSpan.FromSeconds(10)); // 10 second timeout
+ TaskCompletionSource tcs = new();
void CreatedHandler(object s, FileSystemEventArgs e)
{
if (e.ChangeType != WatcherChangeTypes.Created)
+ {
return;
+ }
+
HandleFileCreationAsync(devToolsActivePortFile, tcs, 5, 2).ConfigureAwait(false);
}
@@ -258,11 +276,15 @@ int expectedLines
catch (IOException)
{
if (++retryCount == maxRetries)
+ {
tcs.TrySetException(
new IOException($"Unable to read file '{filePath}' after {maxRetries} attempts")
);
+ }
else
+ {
await Task.Delay(TimeSpan.FromMilliseconds(100 * retryCount)); // Exponential backoff
+ }
}
catch (Exception ex)
{
diff --git a/src/BlazorReports/Services/BrowserServices/Factories/BrowserPageFactory.cs b/src/BlazorReports/Services/BrowserServices/Factories/BrowserPageFactory.cs
index ba5e3e9..50178a4 100644
--- a/src/BlazorReports/Services/BrowserServices/Factories/BrowserPageFactory.cs
+++ b/src/BlazorReports/Services/BrowserServices/Factories/BrowserPageFactory.cs
@@ -22,7 +22,7 @@ public async ValueTask CreateBrowserPage(string targetId, Uri pageU
pageUri,
options.Value.BrowserOptions.ResponseTimeout
);
- var browserPage = new BrowserPage(logger, targetId, pageConnection);
+ BrowserPage browserPage = new(logger, targetId, pageConnection);
return browserPage;
}
}
diff --git a/src/BlazorReports/Services/BrowserServices/Factories/ConnectionFactory.cs b/src/BlazorReports/Services/BrowserServices/Factories/ConnectionFactory.cs
index 40a485d..7ba4fde 100644
--- a/src/BlazorReports/Services/BrowserServices/Factories/ConnectionFactory.cs
+++ b/src/BlazorReports/Services/BrowserServices/Factories/ConnectionFactory.cs
@@ -16,7 +16,7 @@ internal sealed class ConnectionFactory(ILogger logger) : IConnectio
/// The connection
public async ValueTask CreateConnection(Uri uri, TimeSpan responseTimeout)
{
- var connection = new Connection(uri, responseTimeout, logger);
+ Connection connection = new(uri, responseTimeout, logger);
await connection.InitializeAsync();
return connection;
}
diff --git a/src/BlazorReports/Services/BrowserServices/Helpers/ChromeFinder.cs b/src/BlazorReports/Services/BrowserServices/Helpers/ChromeFinder.cs
index 1f2768f..c641686 100644
--- a/src/BlazorReports/Services/BrowserServices/Helpers/ChromeFinder.cs
+++ b/src/BlazorReports/Services/BrowserServices/Helpers/ChromeFinder.cs
@@ -20,7 +20,7 @@ internal static class ChromeFinder
private const string ChromeExecutableNameMac1 = "Google Chrome.app/Contents/MacOS/Google Chrome";
private const string ChromeExecutableNameMac2 = "Chromium.app/Contents/MacOS/Chromium";
private static readonly string[] LinuxDirectoryLocations =
- {
+ [
"/usr/local/sbin",
"/usr/local/bin",
"/usr/sbin",
@@ -28,7 +28,7 @@ internal static class ChromeFinder
"/sbin",
"/bin",
"/opt/microsoft/edge",
- };
+ ];
///
/// Tries to find Chrome
@@ -51,7 +51,7 @@ internal static class ChromeFinder
return pathFromCurrentDirectory;
}
- var directories = new List();
+ List directories = [];
GetApplicationDirectories(directories);
foreach (var exeName in exeNames)
@@ -100,7 +100,10 @@ private static void GetApplicationDirectories(List directories)
private static string? GetPathFromRegistry()
{
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ {
return null;
+ }
+
var key = Registry
.GetValue(
@"HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\App Paths\chrome.exe",
@@ -109,15 +112,18 @@ private static void GetApplicationDirectories(List directories)
)
?.ToString();
- if (key == null)
+ if (key is null)
+ {
return null;
+ }
+
var path = Path.Combine(key, ChromeExecutableNameWin);
return File.Exists(path) ? path : null;
}
private static List GetExeNames()
{
- var exeNames = new List();
+ List exeNames = [];
if (IsWindows)
{
@@ -126,18 +132,17 @@ private static List GetExeNames()
else if (IsLinux)
{
exeNames.AddRange(
- new[]
- {
+ [
ChromeExecutableNameLinux1,
ChromeExecutableNameLinux2,
ChromeExecutableNameLinux3,
ChromeExecutableNameLinux4,
- }
+ ]
);
}
else if (IsMacOs)
{
- exeNames.AddRange(new[] { ChromeExecutableNameMac1, ChromeExecutableNameMac2 });
+ exeNames.AddRange([ChromeExecutableNameMac1, ChromeExecutableNameMac2]);
}
return exeNames;
diff --git a/src/BlazorReports/Services/BrowserServices/Helpers/EdgeFinder.cs b/src/BlazorReports/Services/BrowserServices/Helpers/EdgeFinder.cs
index 68b6bef..cc0ea02 100644
--- a/src/BlazorReports/Services/BrowserServices/Helpers/EdgeFinder.cs
+++ b/src/BlazorReports/Services/BrowserServices/Helpers/EdgeFinder.cs
@@ -19,7 +19,7 @@ internal static class EdgeFinder
private const string ChromeExecutableNameMac = "Microsoft Edge.app/Contents/MacOS/Microsoft Edge";
private static readonly string[] LinuxDirectoryLocations =
- {
+ [
"/usr/local/sbin",
"/usr/local/bin",
"/usr/sbin",
@@ -27,7 +27,7 @@ internal static class EdgeFinder
"/sbin",
"/bin",
"/opt/microsoft/edge",
- };
+ ];
///
/// Tries to find Chrome
@@ -50,7 +50,7 @@ internal static class EdgeFinder
return pathFromCurrentDirectory;
}
- var directories = new List();
+ List directories = [];
GetApplicationDirectories(directories);
foreach (var exeName in exeNames)
@@ -99,7 +99,10 @@ private static void GetApplicationDirectories(List directories)
private static string? GetPathFromRegistry()
{
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ {
return null;
+ }
+
var key = Registry
.GetValue(
@"HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\App Paths\msedge.exe",
@@ -108,15 +111,18 @@ private static void GetApplicationDirectories(List directories)
)
?.ToString();
- if (key == null)
+ if (key is null)
+ {
return null;
+ }
+
var path = Path.Combine(key, EdgeExecutableNameWin);
return File.Exists(path) ? path : null;
}
private static List GetExeNames()
{
- var exeNames = new List();
+ List exeNames = [];
if (IsWindows)
{
@@ -125,12 +131,12 @@ private static List GetExeNames()
else if (IsLinux)
{
exeNames.AddRange(
- new[] { ChromeExecutableNameLinux1, ChromeExecutableNameLinux2, ChromeExecutableNameLinux3 }
+ [ChromeExecutableNameLinux1, ChromeExecutableNameLinux2, ChromeExecutableNameLinux3]
);
}
else if (IsMacOs)
{
- exeNames.AddRange(new[] { ChromeExecutableNameMac });
+ exeNames.AddRange([ChromeExecutableNameMac]);
}
return exeNames;
diff --git a/src/BlazorReports/Services/BrowserServices/Requests/BrowserMessage.cs b/src/BlazorReports/Services/BrowserServices/Requests/BrowserMessage.cs
index ea82118..e04123b 100644
--- a/src/BlazorReports/Services/BrowserServices/Requests/BrowserMessage.cs
+++ b/src/BlazorReports/Services/BrowserServices/Requests/BrowserMessage.cs
@@ -22,7 +22,7 @@ internal sealed class BrowserMessage(string method)
/// The parameters that we want to feed into the browser
///
[JsonPropertyName("params")]
- public Dictionary Parameters { get; } = new();
+ public Dictionary Parameters { get; } = [];
}
///
diff --git a/src/BlazorReports/Services/BrowserServices/Responses/PageGetFrameTreeResponse.cs b/src/BlazorReports/Services/BrowserServices/Responses/PageGetFrameTreeResponse.cs
index bd810eb..2c94801 100644
--- a/src/BlazorReports/Services/BrowserServices/Responses/PageGetFrameTreeResponse.cs
+++ b/src/BlazorReports/Services/BrowserServices/Responses/PageGetFrameTreeResponse.cs
@@ -14,5 +14,4 @@ public sealed record PageGetFrameTreeResponse(BrowserFrameTree FrameTree);
///
[JsonSourceGenerationOptions(PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase)]
[JsonSerializable(typeof(BrowserResultResponse))]
-internal sealed partial class PageGetFrameTreeResponseSerializationContext
- : JsonSerializerContext { }
+internal sealed partial class PageGetFrameTreeResponseSerializationContext : JsonSerializerContext;
diff --git a/src/BlazorReports/Services/ReportService.cs b/src/BlazorReports/Services/ReportService.cs
index c851820..6ba3aae 100644
--- a/src/BlazorReports/Services/ReportService.cs
+++ b/src/BlazorReports/Services/ReportService.cs
@@ -55,17 +55,17 @@ public async ValueTask<
baseStyles = reportRegistry.BaseStyles;
}
- var componentParameters = new Dictionary
+ Dictionary componentParameters = new()
{
{ "BaseStyles", baseStyles },
{ "Data", data },
{ "GlobalAssets", reportRegistry.GlobalAssets },
};
- await using var htmlRenderer = new HtmlRenderer(scope.ServiceProvider, loggerFactory);
+ await using HtmlRenderer htmlRenderer = new(scope.ServiceProvider, loggerFactory);
var html = await htmlRenderer.Dispatcher.InvokeAsync(async () =>
{
- var parameters = ParameterView.FromDictionary(componentParameters);
+ ParameterView parameters = ParameterView.FromDictionary(componentParameters);
var output = await htmlRenderer.RenderComponentAsync(parameters);
return output.ToHtmlString();
});
@@ -110,7 +110,7 @@ public async ValueTask<
baseStyles = reportRegistry.BaseStyles;
}
- var childComponentParameters = new Dictionary();
+ Dictionary childComponentParameters = [];
if (
blazorReport.Component.BaseType == typeof(BlazorReportsBase)
&& reportRegistry.GlobalAssets.Count != 0
@@ -129,7 +129,7 @@ public async ValueTask<
childComponentParameters.Add("Data", data);
}
- var baseComponentParameters = new Dictionary();
+ Dictionary baseComponentParameters = [];
if (!string.IsNullOrEmpty(baseStyles))
{
baseComponentParameters.Add("BaseStyles", baseStyles);
@@ -138,13 +138,13 @@ public async ValueTask<
baseComponentParameters.Add("ChildComponentType", blazorReport.Component);
baseComponentParameters.Add("ChildComponentParameters", childComponentParameters);
- await using var htmlRenderer = new HtmlRenderer(scope.ServiceProvider, loggerFactory);
+ await using HtmlRenderer htmlRenderer = new(scope.ServiceProvider, loggerFactory);
if (blazorReport.OutputFormat == ReportOutputFormat.Pdf)
{
var html = await htmlRenderer.Dispatcher.InvokeAsync(async () =>
{
- var parameters = ParameterView.FromDictionary(baseComponentParameters);
+ ParameterView parameters = ParameterView.FromDictionary(baseComponentParameters);
var output = await htmlRenderer.RenderComponentAsync(parameters);
return output.ToHtmlString();
});
@@ -157,7 +157,7 @@ public async ValueTask<
{
var html = await htmlRenderer.Dispatcher.InvokeAsync(async () =>
{
- var parameters = ParameterView.FromDictionary(baseComponentParameters);
+ ParameterView parameters = ParameterView.FromDictionary(baseComponentParameters);
var output = await htmlRenderer.RenderComponentAsync(parameters);
return output.ToHtmlString();
});