Refactor document name sanitization for consistent filename generation
- Introduced FdsDocumentNames class to centralize the logic for sanitizing document names used in downloads. - Updated FdsMfr to utilize the new SafeFileName method for generating safe filenames. - Enhanced documentation for FdsDocumentNames and its methods to clarify usage and purpose. - Added global.json file to configure testing framework settings.
This commit is contained in:
@@ -329,18 +329,12 @@ public partial class IntranetController
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Download filename for a regenerated document. DocumentName is derived from the user-typed
|
||||
/// invoice title, so it can carry path separators ("Wartung 2025/26") and stray editor markup;
|
||||
/// mirrors the cleanup <c>FdsMfr.GetReportDoc</c> applies to stored documents.
|
||||
/// Download filename for a regenerated document — the one shared sanitiser
|
||||
/// (<see cref="fds.FdsDocumentNames.SafeFileName"/>) that <c>FdsMfr.GetReportDoc</c> also
|
||||
/// applies to stored documents, so both paths name the same DocumentName identically.
|
||||
/// </summary>
|
||||
internal static string SafeDocumentFileName(string documentName, string fallback)
|
||||
{
|
||||
string name = (documentName ?? "").Replace("<p>", "").Replace("</p>", "").Trim();
|
||||
if (name.Length == 0) name = fallback;
|
||||
foreach (char c in Path.GetInvalidFileNameChars())
|
||||
name = name.Replace(c, '_');
|
||||
return name.Length == 0 ? fallback : name;
|
||||
}
|
||||
internal static string SafeDocumentFileName(string documentName, string fallback) =>
|
||||
fds.FdsDocumentNames.SafeFileName(documentName, fallback);
|
||||
|
||||
private async Task<IActionResult> HandleReportDocByName(string fn, string id, string code)
|
||||
{
|
||||
|
||||
@@ -36,6 +36,28 @@ public partial class IntranetController
|
||||
{
|
||||
var result = await render();
|
||||
sw.Stop();
|
||||
|
||||
// The client (postXT) gives up after a fixed timeout and aborts the connection while a
|
||||
// slow render/regenerate-on-miss (ADR 0025) is still running server-side; that work is
|
||||
// deliberately NOT cancelled — the regenerated document must still be stored so the
|
||||
// next click is fast (ADR 0025) — but writing the now-finished result back to a socket
|
||||
// the client already closed would only surface as a low-level framework/Kestrel
|
||||
// exception that never reaches an EventId'd `_logger` call: it is either below the SQL
|
||||
// sink's Warning floor or purely a debugger first-chance notification that never goes
|
||||
// through ILogger at all — exactly the "exception in the debug console but nothing in
|
||||
// fds__debuglog" gap. Recognise the disconnect here instead and log it deliberately, at
|
||||
// Warning, so it is guaranteed to land in fds__debuglog (ADR 0024) — and skip the write.
|
||||
if (HttpContext.RequestAborted.IsCancellationRequested)
|
||||
{
|
||||
FuchsTelemetry.PdfPreviews.Add(1,
|
||||
new KeyValuePair<string, object?>("what", what),
|
||||
new KeyValuePair<string, object?>("outcome", "client-disconnected"));
|
||||
_logger.LogWarning(
|
||||
"PDF preview {What} ref={RefId} user={User} finished in {Ms} ms but the client had already disconnected (timeout) — result discarded",
|
||||
what, refId, UserAccountID, sw.ElapsedMilliseconds);
|
||||
return new EmptyResult();
|
||||
}
|
||||
|
||||
// A draft session that expired between page load and preview click is an expected
|
||||
// client-driven outcome (the browser reopens the draft), not a render failure — keep
|
||||
// it out of the failure telemetry/logging this guard exists to produce.
|
||||
@@ -51,6 +73,20 @@ public partial class IntranetController
|
||||
{
|
||||
sw.Stop();
|
||||
act?.SetStatus(ActivityStatusCode.Error, ex.Message);
|
||||
// Same client-gone rationale as above, but the render itself threw (e.g. it tried to
|
||||
// write partial output to the aborted connection). Still an expected outcome of a
|
||||
// client timeout, not a render defect — logged at Warning, not Error, but still
|
||||
// guaranteed to reach fds__debuglog (ADR 0024) rather than only a debug console.
|
||||
if (HttpContext.RequestAborted.IsCancellationRequested)
|
||||
{
|
||||
FuchsTelemetry.PdfPreviews.Add(1,
|
||||
new KeyValuePair<string, object?>("what", what),
|
||||
new KeyValuePair<string, object?>("outcome", "client-disconnected"));
|
||||
_logger.LogWarning(ex,
|
||||
"PDF preview {What} ref={RefId} user={User} failed after {Ms} ms because the client had already disconnected",
|
||||
what, refId, UserAccountID, sw.ElapsedMilliseconds);
|
||||
return new EmptyResult();
|
||||
}
|
||||
FuchsTelemetry.PdfPreviews.Add(1,
|
||||
new KeyValuePair<string, object?>("what", what),
|
||||
new KeyValuePair<string, object?>("outcome", "failure"));
|
||||
|
||||
Reference in New Issue
Block a user