TX Text Control .NET for Windows Forms

Exceptions and Error Handling

Topic

A document that can't be read, a feature your edition doesn't include, a formula with a typo: TX Text Control reports such errors with exceptions of its own, and many of its methods report expected failures through a return value instead. Knowing which is which tells you where a Windows Forms application needs a try block, where it checks a result, and what it shows the user.

The handlers are in Form1.cs with the TextControl named textControl1. Solutions for specific errors are collected in Troubleshooting.

How TX Text Control Reports Errors

TX Text Control uses three ways:

  • Its own exception classes for errors of the document engine, listed in the next section.
  • Standard .NET exceptions for wrong use of the programming interface. An ArgumentException, ArgumentNullException or ArgumentOutOfRangeException is thrown when the parameter of a method or the value of a property is wrong, and an InvalidOperationException when a method can't be called in the current state of an object.
  • Return values for results that are expected in normal operation. Add methods return false or an AddResult value when an element can't be inserted at the input position, and ServerTextControl.Create returns false when an instance can't be initialized. These cases throw no exception, so check the result.

TX Text Control Exceptions

ExceptionThrown when
FilterExceptionA document can't be converted to or from a format, when it is loaded or saved
LicenseLevelExceptionYour code uses a feature that the licensed edition doesn't include
TextEditorExceptionAn error occurs while text is edited
FormulaExceptionA table formula has invalid syntax or missing parameters
NumberFormatExceptionThe number format of a formula result has invalid syntax
DocumentServer.MergeCanceledExceptionA merge was canceled through DataRowMergedEventArgs.Cancel
DocumentServer.Json.ParserException and its derived classesMailMerge.MergeJsonData receives invalid JSON

The message of a TX Text Control exception contains an error number in parentheses, such as (1-1D01), which identifies the error more exactly than the text. The blog article Text Control Error Navigator Launched shows how to look up these numbers. FormulaException.CharacterIndex and NumberFormatException.CharacterIndex give the one-based position of the first invalid character.

Handle Errors When Loading and Saving

Loading is where most errors come from, because documents come from outside. FilterException.Reason tells the cause as a value of FilterException.FilterError. The following handler lets the user open a DOCX file and explains what went wrong:

private void openButton_Click(object sender, EventArgs e)
{
    using (OpenFileDialog dialog = new OpenFileDialog { Filter = "Word documents|*.docx" })
    {
        if (dialog.ShowDialog(this) != DialogResult.OK)
        {
            return;
        }

        try
        {
            textControl1.Load(dialog.FileName, TXTextControl.StreamType.WordprocessingML);
        }
        catch (TXTextControl.FilterException exception)
        {
            string text = exception.Reason switch
            {
                TXTextControl.FilterException.FilterError.WrongFileType => "The file isn't a Word document.",
                TXTextControl.FilterException.FilterError.Encrypted => "The document is encrypted.",
                TXTextControl.FilterException.FilterError.CannotOpen => "The file couldn't be opened.",
                _ => "The document couldn't be loaded."
            };

            MessageBox.Show(this, $"{text}\n\n{exception.Message}", "Open", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
    }
}

The code works as follows:

  • TextControl.Load throws the FilterException when the file can't be converted.
  • The switch expression turns three values of FilterError into a message for the user; exception.Message contains the text and error number of TX Text Control. Other values include CannotRead, FileTooBig, Unsupported, NotWellFormed and InvalidPassword.
  • An IOException of .NET, such as a file locked by another program, isn't a FilterException. Catch it separately when your application opens files the user chooses.

Document Conversion in Troubleshooting explains each value of FilterError and its fix. Saving throws a FilterException too, for example with NonEmbeddableFont when a PDF can't be created because a font may not be embedded.

Handle Features of Another Edition

A LicenseLevelException means that the code uses a feature of an edition that isn't licensed, for example form fields in the Professional edition. It is an error in the application rather than in a document: fix it by using features of your edition, which Editions lists, or by licensing another edition. Licensing in Troubleshooting shows the messages. Where the application can continue without the feature, catch the exception and tell the user:

private void insertFormFieldButton_Click(object sender, EventArgs e)
{
    try
    {
        textControl1.FormFields.Add(new TXTextControl.TextFormField(1440));
    }
    catch (TXTextControl.LicenseLevelException exception)
    {
        MessageBox.Show(this, exception.Message, "Not available", MessageBoxButtons.OK, MessageBoxIcon.Information);
    }
}

Handle Errors of Background Work

An exception thrown inside Task.Run doesn't reach the user directly. It is stored in the task and thrown again where the task is awaited, on the UI thread, where a try block around the await catches it. The handler needs using System.Threading.Tasks; at the top of Form1.cs:

private async void convertButton_Click(object sender, EventArgs e)
{
    try
    {
        await Task.Run(() =>
        {
            using (TXTextControl.ServerTextControl tx = new TXTextControl.ServerTextControl())
            {
                if (!tx.Create())
                {
                    throw new InvalidOperationException("TX Text Control could not be initialized.");
                }

                tx.Load("contract.docx", TXTextControl.StreamType.WordprocessingML);
                tx.Save("contract.pdf", TXTextControl.StreamType.AdobePDF);
            }
        });

        MessageBox.Show(this, "contract.pdf created.");
    }
    catch (TXTextControl.FilterException exception)
    {
        MessageBox.Show(this, $"{exception.Reason}: {exception.Message}", "Conversion failed");
    }
}

The using block disposes the ServerTextControl also when an exception leaves it. Using ServerTextControl in Desktop Applications describes background work. When a merge is canceled from a DataRowMerged handler, catch the MergeCanceledException in the same way around the merge; Merge Events shows the event.

Catch Exceptions Nobody Handled

An exception that no catch block handles ends the application. To log such exceptions and show a message instead, handle the Application.ThreadException event of Windows Forms in Program.cs before the form is shown. Use it as a last resort, and catch exceptions where you call TX Text Control whenever your code can react to them.

Next Steps