Table of Contents

Diagnostics and strict mode

When a document uses something DocWright can't reproduce exactly, such as a missing font, a field it doesn't evaluate or an effect it doesn't draw, it renders the best result it can and reports what it did. Collect those reports to log them, or turn on strict mode to fail instead.

Collect diagnostics

using DocWright;
using DocWright.Core;
using DocWright.Core.Diagnostics;

var diagnostics = new CollectingConversionDiagnostics();
var options = new ConvertOptions
{
    Diagnostics = diagnostics,
    WarnOnFontSubstitution = true,   // also report every substituted font (DXP3004)
};

using (FileStream input = File.OpenRead("conformance.docx"))
using (FileStream output = File.Create("conformance.pdf"))
{
    converter.Convert(input, output, options);
}

foreach (ConversionDiagnostic d in diagnostics.Snapshot().DistinctBy(d => d.Code))
{
    Console.WriteLine($"[{d.Severity}] {d.Code}: {d.Message}");
}

Console.WriteLine($"{diagnostics.Count} diagnostic(s), errors: {diagnostics.HasErrors}");

Output, for the conformance test document

[Information] DXP2003: Unknown markup 'w:tblStylePr[@]' was preserved opaquely for round-trip.
[Warning] DXP2002: Field 'REF conformanceTarget \h' is not evaluated in this phase; cached result text is used.
2 diagnostic(s), errors: False
Refused: DXP2002: Tracked revision markup rendering is not implemented in this phase; conversion uses Final revision view.

Each ConversionDiagnostic has:

Property Meaning
Code A stable code such as DXP3004. Match on codes, never on message text. The constants are on DocWright.Core.Diagnostics.DiagnosticCodes.
Severity Information, Warning or Error.
Message A human-readable explanation.
Location Where in the document, when known.

CollectingConversionDiagnostics gives you a Snapshot(), Count and HasErrors. The diagnostic codes reference lists every code.

Send them to your logging

Implement IConversionDiagnostics, a single method:

/// <summary>Routes DocWright diagnostics into your own logging.</summary>
internal sealed class ConsoleDiagnostics : IConversionDiagnostics
{
    public void Report(in ConversionDiagnostic diagnostic) =>
        Console.WriteLine($"  [{diagnostic.Severity}] {diagnostic.Code}: {diagnostic.Message}");
}

In ASP.NET Core, write the same class around an ILogger and set it on ConvertOptions.Diagnostics per request.

Strict mode

With StrictMode = true, anything that would have been reported as unsupported throws UnsupportedFeatureException instead. Its DiagnosticCode says what was refused:

using DocWright;
using DocWright.Core;
using DocWright.Core.Diagnostics;

try
{
    using FileStream input = File.OpenRead("conformance.docx");
    converter.Convert(input, Stream.Null, new ConvertOptions
    {
        StrictMode = true,
        RenderRevisions = true,   // not implemented yet, so strict mode refuses it
    });
}
catch (UnsupportedFeatureException ex)
{
    Console.WriteLine($"Refused: {ex.DiagnosticCode}: {ex.Message}");
}

Use strict mode when a silently degraded document is worse than no document. Legal and regulatory output is the usual case. SaveOptions.StrictMode and ReportRunOptions.StrictMode apply the same rule to saving and to running reports.

What the common codes mean

Code Meaning What to do
DXP2002 A feature is not implemented; the closest supported behaviour was used. Usually nothing. Check the message if the output looks wrong.
DXP2003 Markup DocWright does not model was preserved as-is, so it survives a save. Nothing. It is information.
DXP3001 A font was substituted. Install the font, or add it to FontDirectories.
DXP3004 A summary of substitutions (with WarnOnFontSubstitution). As above.
conformance.pdf
The conformance test document rendered despite the reported diagnostics
The document still renders completely. Diagnostics describe the output; they don't stop it.