ReportIssue.AspNetCore
0.3.8
dotnet add package ReportIssue.AspNetCore --version 0.3.8
NuGet\Install-Package ReportIssue.AspNetCore -Version 0.3.8
<PackageReference Include="ReportIssue.AspNetCore" Version="0.3.8" />
<PackageVersion Include="ReportIssue.AspNetCore" Version="0.3.8" />
<PackageReference Include="ReportIssue.AspNetCore" />
paket add ReportIssue.AspNetCore --version 0.3.8
#r "nuget: ReportIssue.AspNetCore, 0.3.8"
#:package ReportIssue.AspNetCore@0.3.8
#addin nuget:?package=ReportIssue.AspNetCore&version=0.3.8
#tool nuget:?package=ReportIssue.AspNetCore&version=0.3.8
ReportIssue.AspNetCore
Reusable ASP.NET Core backend package for report-issue workflows.
Targets .NET 8 and uses ASP.NET Core Minimal APIs. Includes default SQL Server persistence, file storage, email notifications, and adapters for host services.
Install
The public package ID is ReportIssue.AspNetCore. After publication to NuGet.org,
install it from the public feed:
dotnet add package ReportIssue.AspNetCore --version 0.3.8 --source https://api.nuget.org/v3/index.json
In Visual Studio, select nuget.org in Manage NuGet Packages and search
for ReportIssue.AspNetCore.
Migration from the previous package
Replace the Tra.Bilisim.ReportIssue.AspNetCore package reference with
ReportIssue.AspNetCore and update using directives from
Tra.Bilisim.ReportIssue.AspNetCore.* to ReportIssue.AspNetCore.*.
The assembly name also changes to ReportIssue.AspNetCore.
Install the new package explicitly and remove the previous package reference.
Update any assembly-qualified references to use the new assembly name.
Register
using ReportIssue.AspNetCore.DependencyInjection;
using ReportIssue.AspNetCore.Options;
builder.Services.AddReportIssue(options =>
{
options.ConnectionString = builder.Configuration.GetConnectionString("AppDb");
options.Recipients = ["support@example.com"];
options.AdminRoles = ["Admin"];
options.Notification.Enabled = true;
options.Notification.DeliveryMode = ReportIssueEmailDeliveryMode.Smtp;
options.Notification.SmtpHost = "smtp.example.com";
options.Notification.FromAddress = "robot@example.com";
options.Notification.UserName = "robot@example.com";
options.Notification.Password = "...";
// Optional. Default is Separate; use MergeWithNetwork to append socket
// activity to network_logs.json/html in chronological order.
options.SocketLogAttachmentMode = SocketLogAttachmentMode.MergeWithNetwork;
});
app.UseRateLimiter();
app.MapReportIssueEndpoints();
Custom or third-party email delivery
When the host already sends mail through an HTTP provider, a queue, or its own
mail facade, do not add SMTP settings. Select custom delivery and replace only
the package sender after calling AddReportIssue:
using ReportIssue.AspNetCore.Abstractions;
using ReportIssue.AspNetCore.DependencyInjection;
using ReportIssue.AspNetCore.Models;
using ReportIssue.AspNetCore.Options;
builder.Services.AddReportIssue(options =>
{
options.ConnectionString = builder.Configuration.GetConnectionString("AppDb");
options.Recipients = ["support@example.com"];
options.AdminRoles = ["Admin"];
options.Notification.Enabled = true;
options.Notification.DeliveryMode = ReportIssueEmailDeliveryMode.Custom;
});
builder.Services.UseReportIssueEmailSender<HostReportIssueEmailSender>();
public sealed class HostReportIssueEmailSender : IReportIssueEmailSender
{
public Task SendAsync(ReportIssueEmailMessage message, CancellationToken cancellationToken = default)
{
// Send message.To, message.Subject, message.Body and message.Attachments
// through the host's own provider. Do not retain attachment streams.
return Task.CompletedTask;
}
}
The custom sender receives provider-neutral message data. SMTP credentials
remain in ReportIssueOptions.Notification and are not copied into messages
created by the package.
Socket log attachments
SocketLogAttachmentMode controls notification attachments:
Separate(default): createsnetwork_logs.*andsocket_logs.*separately.MergeWithNetwork: creates one chronologically orderednetwork_logs.jsonandnetwork_logs.html; each entry hassource(networkorsocket) andts.
Network entries use their request start timestamp as ts (falling back to the
response timestamp). Their original requestTs and responseTs fields are retained.
Run sql/report-issue.sql against the host database before using the default store.
Security: report content is untrusted
All report fields, attachments, console logs, and request metadata are
attacker-controlled. The default metadata provider replaces userId, userName,
email, and userAgent with server-side request/claim values. It currently keeps
the roles array supplied in client metadata; stored ReporterRoles is therefore
display-only, untrusted data and must never be used for authorization. Endpoint
authorization uses the authenticated principal and the configured policies or
AdminRoles, not stored report metadata. The package HTML-encodes report values
inserted into its notification email.
The host application's report list/detail UI must render report values as text
(for example, React {value} or Razor's default output encoding), never with
innerHTML, Html.Raw, or an equivalent raw-HTML API. Do not serve uploaded or
generated HTML under the application origin. Set a restrictive Content Security
Policy on the host UI; a suitable baseline is
default-src 'self'; script-src 'self'; object-src 'none'; base-uri 'self'; img-src 'self' data:.
Package-owned database email templates
Version 0.3.8 uses the package-owned dbo.ReportIssueEmailTemplates table by
default. The canonical sql/report-issue.sql script creates the table and
inserts active REPORT_ISSUE rows for TR and EN. Existing rows are not
overwritten when the script is rerun. The provider never probes a host
application's generic EmailTemplate table.
The defaults are equivalent to:
builder.Services.AddReportIssue(options =>
{
options.ConnectionString = builder.Configuration.GetConnectionString("AppDb");
options.Recipients = ["support@example.com"];
options.AdminRoles = ["Admin"];
options.Notification.Enabled = true;
options.Notification.TemplateSource = ReportIssueTemplateSource.Database;
options.Notification.FallbackToInlineTemplate = false;
options.Notification.DatabaseTemplate.TableName = "dbo.ReportIssueEmailTemplates";
options.Notification.DatabaseTemplate.TypeColumn = "Type";
options.Notification.DatabaseTemplate.LanguageColumn = "Language";
options.Notification.DatabaseTemplate.SubjectColumn = "Subject";
options.Notification.DatabaseTemplate.BodyColumn = "Html";
options.Notification.DatabaseTemplate.StatusColumn = "Status";
options.Notification.DatabaseTemplate.Type = "REPORT_ISSUE";
options.Notification.DatabaseTemplate.Language = "TR";
options.Notification.DatabaseTemplate.FallbackLanguage = "EN";
});
The provider reads active rows using the same connection string as the report
tables, prefers the configured language, then FallbackLanguage, and finally
another active row with the same type. To opt into an inline template, set
TemplateSource = ReportIssueTemplateSource.Inline explicitly and configure
Subject/BodyTemplate.
Permission-based admin endpoints
If a host project uses permissions instead of roles, define an ASP.NET Core authorization policy and pass its name:
builder.Services.AddAuthorization(options =>
{
options.AddPolicy("ReportIssueAdmin", policy =>
{
policy.RequireAuthenticatedUser();
policy.RequireClaim("permission", "ReportIssue.List", "ReportIssue.Detail");
});
});
builder.Services.AddReportIssue(options =>
{
options.ConnectionString = "...";
options.AdminAuthorizationPolicy = "ReportIssueAdmin";
});
For endpoint-metadata based permission attributes:
options.RequireAdminRole = false;
options.ConfigureAdminEndpoints = endpoint =>
endpoint.WithMetadata(new HasPermissionAttribute("ReportIssue.List,ReportIssue.Detail"));
MVC action filters do not run on Minimal API endpoints; use an authorization policy/handler for those cases.
See REPORT_ISSUE_INTEGRATION.md for DB-first notes and override examples.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- Microsoft.Data.SqlClient (>= 5.1.5)
- Microsoft.EntityFrameworkCore (>= 8.0.7)
- Microsoft.EntityFrameworkCore.SqlServer (>= 8.0.7)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.3.8 | 34 | 10/14/2026 |