Manual document creation and processing is a high-effort process and error-prone. Information is manually typed into documents, older versions are reused (copy and change of existing documents) or documents are created from scratch each time a new document is required. Contract Lifecycle Challenges Specifically for business critical documents such as contracts and agreements, manual processes can be dangerous in many ways. The following table lists typical challenges with agreement processes: Preparation Collaboration Signing Managing Errors due to manually entered data into contracts. Usage of different "red-lining" tools and versions (MS Word). No central portal to see status of the signing process. Errors due to manually entered data into contracts. Delays due to long preparation process. No central control over tracked changes. Delays due to missing information. No central contract repository or search. No data binding to CRM and ERP systems. Poor user experience. Delays due to wrong routing. Security and data privacy For this sample, we take a look at the Preparation column and specifically the first reason: Errors due to manually entered data into contracts. To avoid this, reusable text snippets should be used and maintained at a central location. The following screenshot shows the sample that allows users to insert formatted snippets. Creating Snippets The interface allows users to create new snippets by selecting any text in the document and clicking New Snippet. All elements are saved within the snippet including formatted text, merge and form fields, tables and other document elements. Technically, the snippet is saved using the Selection.save method and is stored server-side along with an HTML preview generated by TX Text Control. [HttpPost] public bool Create(string document, string name) { var snippetName = _applicationSettings.SnippetDirectory + "/" + Path.GetInvalidFileNameChars().Aggregate(name, (f, c) => f.Replace(c, '_').Replace(' ', '_')); using (TXTextControl.ServerTextControl tx = new TXTextControl.ServerTextControl()) { tx.Create(); // load the snippet tx.Load(Convert.FromBase64String(document), TXTextControl.BinaryStreamType.InternalUnicodeFormat); // select 200 chars as a preview tx.Select(0, 200); // save the body of the snippet TXTextControl.SaveSettings saveSettings = new TXTextControl.SaveSettings() { CssSaveMode = TXTextControl.CssSaveMode.Inline }; tx.Selection.Save(out string htmlString, TXTextControl.StringStreamType.HTMLFormat, saveSettings); TextReader reader = new StringReader(htmlString); HtmlDocument doc = new HtmlDocument(); doc.Load(reader); HtmlNode bodyNode = doc.DocumentNode.SelectSingleNode("/html/body"); System.IO.File.WriteAllText(snippetName + ".htm", bodyNode.InnerHtml); } // store the actual snippet in the Text Control format System.IO.File.WriteAllBytes(snippetName + ".tx", Convert.FromBase64String(document)); return true; } Loading Snippets In case a snippet is inserted into the document, the Selection.load method is used to load the document asynchronously. function getSnippet(snippetName, snippetFormat) { var serviceURL = "@Url.Action("Content", "Snippets")"; console.log(snippetName); $.ajax({ type: "POST", url: serviceURL, data: { name: snippetName, format: snippetFormat }, success: successFunc, error: errorFunc }); function successFunc(data, status) { if (snippetFormat == "HTM") document.querySelector('[tx-snippet-name="' + snippetName + '"] .snippet-preview').innerHTML = data + "..."; else TXTextControl.selection.load(TXTextControl.StreamType.InternalUnicodeFormat, data); } function errorFunc() { $("#myToast .toast-body").text("Error! :-("); $("#myToast").toast("show"); } } Managing Snippets The sample also implements an overview page that lists all created snippets. This section allows you to edit and delete existing snippets and to create new snippets from scratch. Test this on your own and fork our sample project on GitHub.