<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~files/atom-premium.xsl"?>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:feedpress="https://feed.press/xmlns" xmlns:media="http://search.yahoo.com/mrss/" xmlns:podcast="https://podcastindex.org/namespace/1.0">
  <feedpress:locale>en</feedpress:locale>
  <link rel="hub" href="https://feedpress.superfeedr.com/"/>
  <logo>https://static.feedpress.com/logo/telerik-blogs-productivity-document-processing-6185279b7c73f.jpg</logo>
  <title type="text">Telerik Blogs | Productivity | Document Processing</title>
  <subtitle type="text">The official blog of Progress Telerik - expert articles and tutorials for developers.</subtitle>
  <id>uuid:f5b6224a-67d4-4fb8-971c-30715ee47126;id=4754</id>
  <updated>2026-04-11T21:18:52Z</updated>
  <category term="Blogs"/>
  <contributor>
    <name>Tanya Dimitrova </name>
  </contributor>
  <contributor>
    <name>Dimitar Karamfilov </name>
  </contributor>
  <contributor>
    <name>Yoan Krumov </name>
  </contributor>
  <contributor>
    <name>Svilen Pavlov </name>
  </contributor>
  <link rel="alternate" href="https://www.telerik.com/"/>
  <link rel="self" type="application/atom+xml" href="https://feeds.telerik.com/blogs/productivity-document-processing"/>
  <entry>
    <id>urn:uuid:1f05ab79-badb-485a-b3f4-0c01865d5b9a</id>
    <title type="text">Creating a Custom AI Agent with Telerik Tools 1: Configuring an LLM for Azure or Ollama</title>
    <summary type="text">Create a custom RAG-enabled AI agent for an LLM with Progress Telerik Document Processing Libraries AI connectors.</summary>
    <published>2026-04-07T20:50:49Z</published>
    <updated>2026-04-11T21:18:52Z</updated>
    <author>
      <name>Peter Vogel </name>
    </author>
    <link rel="alternate" href="https://feeds.telerik.com/link/23072/17315472/creating-custom-ai-agent-telerik-tools-1-configuring-llm-azure-ollama"/>
    <content type="text"><![CDATA[<p><span class="featured">Create a custom RAG-enabled AI agent for an LLM with Progress Telerik Document Processing Libraries AI connectors.</span></p><p>The problem with general-purpose AI agents is that they are subject to &ldquo;hallucinations&rdquo; (these days, we say that those agents produce answers that aren&rsquo;t &ldquo;grounded&rdquo;).</p><p>One solution to that problem is to create a custom AI agent with your own content and have your agent use that content to generate grounded answers (this is referred to as <a target="_blank" href="https://www.telerik.com/blogs/fixing-llms-retrieval-augmented-generation">Retrieval Augmented Generation</a> or RAG). Effectively, you can create a dedicated, reliable AI assistant for your users for any aspect of your organization.</p><p>Progress Telerik <a target="_blank" href="https://www.telerik.com/document-processing-libraries">Document Processing Libraries</a> (DPL) include a set of AI connectors that support creating those custom RAG-enabled AI agents of your own using any of the existing Large Language Models (LLMs) available to you in Azure or on your own computer/server using Ollama. And, once that agent is created, Telerik UI tools will let you integrate it into any application.</p><p>So, this post kicks off a series of posts where I&rsquo;m going to walk you through <em>all</em> of the steps you need to create a custom AI agent by using Telerik DPL (and related AI tools), integrated with an LLM available on Azure or in Ollama. Once you&rsquo;ve created an agent, I&rsquo;ll show you how to add that custom agent into your application&rsquo;s UI using AI-enabled Telerik UI components in either JavaScript or Blazor (though you could also create your frontend in ASP.NET, Windows Forms or .NET MAUI).</p><p>But &hellip; having said that, if all you want to do is add an AI prompt to your application, then, thanks to Telerik tools, this post might be the only one you need. At the end of this post, I&rsquo;ll show you how to create a simple frontend for your application to use your LLM. In fact, if you&rsquo;ve already got an LLM deployed (which is what this post is about), you might want to skip the rest of this post and go directly to that last section.</p><h2 id="picking-your-llm-provider">Picking Your LLM Provider</h2><p>If you stick with Microsoft&rsquo;s offerings, you actually have three options for creating the LLM your application will use. The good news here is that, thanks to Microsoft and Telerik tools, it doesn&rsquo;t make much difference to your code which of those three options you use.</p><p>Your three choices are:</p><ul><li><p><strong>Microsoft Foundry</strong>: This gives you access to a wide variety of LLMs from multiple providers (including the OpenAI LLMs), while giving you integration with Azure security. Microsoft Foundry also gives you extensive monitoring for your LLM, enables data privacy and supports integration with other Azure services. This is Microsoft&rsquo;s recommended option. I&rsquo;ll call this the &ldquo;Foundry option.&rdquo;</p></li><li><p><strong>Azure OpenAI</strong>: This is the easiest option to set up but also provides the least access to Azure functionality. The Azure OpenAI option gives you access only to OpenAI&rsquo;s LLMs and only limited integration with other Azure resources (principally, security). With this choice you do, however, get access to the latest OpenAI LLMs, potentially before they show up in Microsoft Foundry. I&rsquo;ll call this the &ldquo;OpenAI-only option.&rdquo;</p></li><li><p><strong>Ollama</strong>: Unlike OpenAI or Microsoft Foundry, Ollama runs on your local computer, rather than in the cloud. Since there are no API fees, that makes Ollama an attractive choice for cheaper solutions (provided you have a powerful enough development computer). I&rsquo;ll call this the &ldquo;Client-side option.&rdquo;</p></li></ul><aside><hr data-sf-ec-immutable="" /><div class="row"><div class="col-4 u-normal-full u-small-mb0"><h4 class="u-fs20 u-fw5 u-lh125 u-mb0">Loading, Accessing and Converting Office and PDF Documents with Telerik Document Processing Libraries</h4></div><div class="col-8"><p class="u-fs16 u-mb0">Here&rsquo;s what you need to get started with <a target="_blank" href="https://www.telerik.com/blogs/loading-accessing-converting-office-pdf-documents-telerik-document-processing-libraries">Telerik Document Processing Libraries to work with PDF, Word and Excel files</a> (and, like any good suite, make all those document types look very much alike).</p></div></div><hr class="u-mb3" /></aside><h2 id="setting-up-openaimicrosoft-foundry">Setting Up OpenAI/Microsoft Foundry</h2><p>While I&rsquo;m treating the OpenAI-only option as a separate case from the Foundry option, the OpenAI-only option is actually hosted in Microsoft Foundry. As a result, the processes for setting up the OpenAI-only or the Foundry option are very similar:</p><ol><li>In the Azure portal at <a target="_blank" href="http://portal.azure.com">portal.azure.com</a>, create an Azure resource.</li><li>In the Microsoft Foundry portal at <a target="_blank" href="http://ai.azure.com">ai.azure.com</a>, add an LLM&mdash;a &ldquo;deployment&rdquo;&mdash;to that resource.</li></ol><h3 id="creating-the-resource">Creating the Resource</h3><p>To start, surf to the <a target="_blank" href="https://portal.azure.com">Azure Portal</a> and search for Microsoft Foundry. On the Microsoft Foundry page, in the menu on the left, expand the <strong>Use with Foundry</strong> node and click on either:</p><ul><li>The Foundry node for the Foundry option</li><li>The Azure OpenAI node for the OpenAI-only options</li></ul><p>Either choice will open a page on the right. On that new page, click on the +Create menu choice at the left end of the menu running across the top of the page. That will start the wizard that will create your Azure resource.</p><p>If you opened this page from the Foundry node, you&rsquo;ll start the wizard for creating your Foundry resource.</p><p>If you opened this page from the OpenAI node, you&rsquo;ll get a dropdown list with two choices: OpenAI and Microsoft Foundry. This is, effectively, your last chance to switch to the Foundry option instead of OpenAI-only. Pick the OpenAI choice to open the wizard for creating an OpenAI-only resource.</p><p>Regardless of which wizard you&rsquo;ve invoked, on the wizard&rsquo;s first page you&rsquo;ll need to provide a resource group, a name for your resource and a region for your LLM to run in. In addition, on the first page:</p><ul><li>For a Foundry resource, you&rsquo;ll need to provide a default project name</li><li>For an Azure OpenAI resource, you&rsquo;ll need to select a <a target="_blank" href="https://azure.microsoft.com/en-ca/pricing/details/cognitive-services/openai-service/">pricing tier</a></li></ul><p>After that, it&rsquo;s just a matter of &ldquo;Next&rdquo;ing your way through the rest of the wizard&rsquo;s tabs.</p><h3 id="setting-network-access">Setting Network Access</h3><p>Both the Foundry and OpenAI-only wizards include a Network tab to control access to your resource. You have three choices on the Network tab:</p><ul><li>All networks: Gives access to your resource from anywhere</li><li>Selected networks: Limits access to a subnet on a specific Azure virtual network, plus a list of IP addresses (e.g., your development computer)</li><li>Disabled: Allows access only through a private endpoint on an Azure virtual network</li></ul><p>You would use the last two options if you were going to run your application on a VM on a virtual network or in an App Service. You don&rsquo;t need to use the network choices to control access to your resource. You could control access to your LLM just through the resource&rsquo;s Access Control/IAM roles, for example, or your application&rsquo;s built-in security. However, for a production application, you should always lean toward more control rather than less and pick whichever of these options that makes sense for limiting network access to your resource.</p><h3 id="setting-foundry-option">Setting Foundry Option</h3><p>The Foundry wizard includes three additional tabs that the OpenAI wizard does not:</p><ul><li>Storage: This tab provides access to multiple additional Azure resources. You can:<br />&nbsp;&nbsp;&nbsp; &raquo; Tie your resource to an Azure Key Vault where you can store passwords or other credentials that agents in your resource will need<br />&nbsp;&nbsp;&nbsp; &raquo; Turn on Application Insights to log activities in your resource<br />&nbsp;&nbsp;&nbsp; &raquo; Tie in an AI Search agent that your resource can access when processing requests<br />&nbsp;&nbsp;&nbsp; &raquo; Add a Storage account to hold uploaded files<br />&nbsp;&nbsp;&nbsp; &raquo; Integrate a CosmosDB account to hold conversation history.</li><li>Identity: Assign a <a target="_blank" href="https://www.telerik.com/blogs/coding-azure-4-securing-web-service-app-service-access-azure-sql-database">Managed Identity</a> to your resource to support agents that access other Azure resources</li><li>Encryption: Use your own encryption keys for any data stored by your resource</li></ul><p>For a proof-of-concept project, you can take the defaults on all these tabs.</p><p>Both wizards finish with the standard Tags tab and Review-and-create tab. When you get to that last tab, click the Create button to create your resource.</p><h3 id="selecting-an-llm">Selecting an LLM</h3><p>Your application interacts with a deployed instance of some LLM so your next step is to create a deployment that uses one of the LLMs available to your resource.</p><p>To do that, navigate to your resource and, on the Overview page, click on the Go to Foundry portal link at the top of the page. This will open a new tab in your browser displaying the <a target="_blank" href="http://ai.azure.com">ai.azure.com</a> portal. This is where you will select the LLM you&rsquo;ll use in your deployment.</p><p>To create a deployment, on the Microsoft Foundry page for your resource, in the menu on the left, click on the Model catalog node. That will take you to a page where you can select your LLM.</p><p>A warning: Over and above whatever criteria you have for getting the right model for your application, selecting a model may require some trial-and-error poking around. That&rsquo;s because:</p><ul><li>Some models are deprecated or may not be available for your resource (e.g., selecting a non-OpenAI LLM for an OpenAI-only resource).</li><li>You may not be eligible for some models.</li><li>Your subscription may not have the necessary resources to support a model.</li><li>The model you select may not support the processing you want to implement.</li></ul><p>Once you open the page listing available LLMs, if you got to the page from a:</p><ul><li>Foundry resource: You can browse the lists of LLMs from a variety of providers or you can search for an LLM using the search box just below those lists</li><li>OpenAI resource: You can browse the list of OpenAI LLMs</li></ul><p>When you select an LLM, Azure will display a page with high-level information about your LLM. For my case study, I created three deployments, one each for these three LLMs:</p><ul><li>gpt-5.2-chat LLM as an example of a Foundry resource</li><li>gpt-5-chat LLM as an example of an Azure OpenAI-only resource</li><li>text-embedding-3-large as an example of an LLM with specific features (I&rsquo;ll use it in a later post on querying with Telerik AI connectors).</li></ul><h3 id="creating-a-deployment">Creating a Deployment</h3><p>To create your deployment, at the top of the page, click the button labeled &ldquo;Use this model.&rdquo; That will display a dialog where you can customize the LLM you&rsquo;ve chosen, including giving your deployment a name (your deployment&rsquo;s name will default to the name of your LLM). Click on the button at the bottom of the page labeled &ldquo;Create resource and deploy&rdquo; &hellip; and then be patient because this can take a moment.</p><p>After your deployment is created with your selected LLM:</p><ul><li>In a Foundry resource, you&rsquo;ll be taken to the page describing your deployment.</li><li>In an OpenAI-only resource, you&rsquo;ll be taken to an Overview page. In the menu on the left, click on the Models + endpoints node to open a list of your deployments. Select the deployment you just created to be taken to the page describing your deployment.</li></ul><p>Once you&rsquo;re on your deployment&rsquo;s page, you need three required pieces of information from the page to use in your application and one optional piece:</p><ul><li>Name: Displayed at the top of the page.</li><li>Authentication information: Your deployment will default to Key authentication, which is fine for a proof-of-concept application (you can switch to Entra Id authentication for production, but the code to access your resource will get more complicated). Assuming that you stick with Key Authentication, copy the Key provided on this page.</li><li>URL: At the top of your deployment&rsquo;s page, find the Target Uri and copy the first segment of the URL provided (i.e., everything from the &ldquo;https://&rdquo; and up to, but not including, the first forward slash in the URL).</li><li>Version: Depending on how you intend to use your LLM, you may not need this, but it does no harm to grab it now. Again, the easiest place to get this is from the sample code. Look for the string put in the variable called api-version (it will look like a date, e.g., &ldquo;2025-12-01&rdquo;).</li></ul><h3 id="returning-to-your-deployment">Returning to Your Deployment</h3><p>To return to your resource or your model, first surf to <a target="_blank" href="http://ai.azure.com">ai.azure.com</a> and sign in. This portal is, currently, in the process of migrating to a new UI, so:</p><ul><li>If you get the &ldquo;old&rdquo; UI then, you may get a list of Foundry and Open AI resources. If so, pick the resource you want to go to the resource&rsquo;s page. On the other hand, you may just be taken directly to one of your resources. Either way, in the menu on the left, select the Models + endpoints node to see a list of your deployments.</li><li>If you <em>don&rsquo;t</em> get that list of your resources &hellip; well, then you&rsquo;re probably in the new UI and, at this point, I&rsquo;d recommend using the toggle at the top of the page to return to the old UI so you can follow along.</li></ul><p>You have more to do to create your own custom RAG-enabled AI agent (load your own content, for example). But if all you want is an application that integrates an AI prompt, you&rsquo;ve done everything you need to support that. You just need to create a frontend that lets the user query your LLM&rsquo;s deployment. The Telerik AI Prompt will let you do that with minimum effort. I&rsquo;ll cover that after showing how to set up the client-side option with Ollama.</p><h2 id="setting-up-ollama">Setting Up Ollama</h2><p>To implement the client-side option, you first need to <a target="_blank" href="https://ollama.com/download/windows">download Ollama</a> and install it. To confirm that Ollama installed successfully, open a command window and enter <code>ollama</code>. You should get back a list of Ollama commands.</p><p>You next need to add the LLM you want to use to Ollama. To do that, open a command window and use Ollama&rsquo;s <code>pull</code> command to install one of the LLMs from the <a target="_blank" href="https://ollama.com/library">Ollama registry</a>. This command installs OpenAI&rsquo;s <a target="_blank" href="https://openai.com/index/introducing-gpt-oss/">gpt-oss</a> LLM:</p><pre class=" language-ollama"><code class="prism  language-ollama">ollama pull gpt-oss
</code></pre><p>After using the <code>pull</code> command, you can use Ollama&rsquo;s <code>list</code> command (which displays the installed LLMs) to confirm your installation.</p><p>The Ollama server <em>should</em> start automatically after installation (and after every reboot) and <em>should</em> be listening on port 11434 on localhost. You can confirm that by using Ollama&rsquo;s <code>serve</code> command. If server isn&rsquo;t running, it will start and report the address the server is listening on. If the server is already running, you&rsquo;ll get an error message that includes address that Ollama is listening on.</p><p>Make a note of the address (probably http://localhost:11434) and the name of the LLM you installed&mdash;you&rsquo;ll need both in your code.</p><p>I&rsquo;m building up to a creating a custom AI agent over this series of posts. But, at this point, you&rsquo;ve done everything you need to create an application with an AI prompt&mdash;it&rsquo;s just a matter of adding a frontend to your LLM.</p><h2 id="adding-a-front-end">Adding a Front End</h2><p>In my next posts, I&rsquo;ll use Telerik Document Processing Library tools to create applications that allow users to apply AI to documents. However, once you&rsquo;ve created an LLM deployment, you can tie that deployment into your application&rsquo;s UI with a few lines of code in your application&rsquo;s Program.cs file and then query your LLM through the Telerik AI Prompt component in your application&rsquo;s UI.</p><p>To do that in a .NET 8 or later application, you first need to add the Microsoft.Extensions.AI.OpenAI NuGet package to your application. After that, you need to tie your model into your application by adding the following code to your application&rsquo;s Program.cs file, inserting the information about your LLM that you gathered from your deployment&rsquo;s information page.</p><p>For either of my Foundry or OpenAI-only options that code looks like this:</p><pre class=" language-csharp"><code class="prism  language-csharp">builder<span class="token punctuation">.</span>Services<span class="token punctuation">.</span><span class="token function">AddSingleton</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">AzureOpenAIClient</span><span class="token punctuation">(</span>
     <span class="token keyword">new</span> <span class="token class-name">Uri</span><span class="token punctuation">(</span>&ldquo;<span class="token operator">&lt;</span>url<span class="token operator">&gt;</span>&rdquo;<span class="token punctuation">)</span><span class="token punctuation">,</span>
     <span class="token keyword">new</span> <span class="token class-name">AzureKeyCredential</span><span class="token punctuation">(</span>&ldquo;<span class="token operator">&lt;</span>key<span class="token operator">&gt;</span>&rdquo;<span class="token punctuation">)</span>
 <span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
builder<span class="token punctuation">.</span>Services<span class="token punctuation">.</span><span class="token function">AddChatClient</span><span class="token punctuation">(</span>services <span class="token operator">=</span><span class="token operator">&gt;</span> 
         services<span class="token punctuation">.</span><span class="token generic-method function">GetRequiredService<span class="token punctuation">&lt;</span>AzureOpenAIClient<span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span>
            <span class="token punctuation">.</span><span class="token function">GetChatClient</span><span class="token punctuation">(</span><span class="token operator">&lt;</span>deployment name<span class="token operator">&gt;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">AsIChatClient</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre><p>For Ollama, in addition to adding the Microsoft.Extensions.AI.OpenAI NuGet package, you&rsquo;ll also need to add the OllamaSharp and Microsoft.SemanticKernel.Connectors.Ollama packages. After that, this single line of code will integrate Ollama into your application:</p><pre class=" language-csharp"><code class="prism  language-csharp">builder<span class="token punctuation">.</span>Services<span class="token punctuation">.</span><span class="token generic-method function">AddSingleton<span class="token punctuation">&lt;</span>IChatClient<span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span>
    sp <span class="token operator">=</span><span class="token operator">&gt;</span> <span class="token keyword">new</span> <span class="token class-name">OllamaApiClient</span><span class="token punctuation">(</span><span class="token string">"&lt;Ollama address&gt;"</span><span class="token punctuation">,</span> <span class="token string">"&lt;model name&gt;"</span><span class="token punctuation">)</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre><p>Your last step is to add the Telerik AIPrompt to your application&rsquo;s UI (available in <a target="_blank" href="https://www.telerik.com/design-system/docs/components/aiprompt/">JavaScript for Kendo UI</a>, <a target="_blank" href="https://www.telerik.com/blazor-ui/documentation/components/aiprompt/overview">Blazor</a>, <a target="_blank" href="https://www.telerik.com/products/aspnet-ajax/ai-prompt.aspx">ASP.NET AJAX</a>, <a target="_blank" href="https://www.telerik.com/products/winforms/aiprompt.aspx">WinForms</a> and <a target="_blank" href="https://www.telerik.com/maui-ui/aiprompt">.NET MAUI</a>). That can be as simple as this in an application that supports Razor (e.g., ASP.NET or Blazor):</p><pre class=" language-razor"><code class="prism  language-razor">&lt;TelerikAIPrompt/&gt;
</code></pre><p>And that would give you this UI:</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-03/ai-ui-1-combined.png?sfvrsn=5736fd30_2" alt="The basic AI Prompt display showing a textbox with a “Generate” button underneath it. Above the textbox are two additional buttons: “Ask AI” and “Output”" /></p><p>In a JavaScript application, you&rsquo;ll need to add a <code>&lt;div&gt;</code> element, set the element&rsquo;s <code>id</code> attribute, and write a couple lines of JavaScript code. I&rsquo;ll cover that in a later post in this series.</p><p>You can now start your application, enter a prompt into the AIPrompt component (e.g., &ldquo;Tell me about RAG-enabled AI applications&rdquo;) and get a response.</p><p>There&rsquo;s obviously far more that you can do with the AI Prompt &hellip; and I&rsquo;ll return to that after my next post. Before that, however, I&rsquo;m going to roll in Telerik Document Processing Library to let you load the content for your custom AI agent.</p><hr /><p>Explore Telerik Document Processing Libraries, plus component libraries, reporting and more with a free trial of the Telerik DevCraft bundle:</p><p><a class="Btn" target="_blank" href="https://www.telerik.com/download">Try DevCraft</a></p><img src="https://feeds.telerik.com/link/23072/17315472.gif" height="1" width="1"/>]]></content>
  </entry>
  <entry>
    <id>urn:uuid:88e4a370-d2a2-4d78-ae1f-86792f7c61e1</id>
    <title type="text">Loading, Accessing and Converting Office and PDF Documents with Telerik Document Processing Libraries</title>
    <summary type="text">Here’s what you need to get started with Telerik Document Processing Libraries to work with PDF, Word and Excel files (and, like any good suite, make all those document types look very much alike).</summary>
    <published>2026-03-31T15:30:52Z</published>
    <updated>2026-04-11T21:18:52Z</updated>
    <author>
      <name>Peter Vogel </name>
    </author>
    <link rel="alternate" href="https://feeds.telerik.com/link/23072/17310582/loading-accessing-converting-office-pdf-documents-telerik-document-processing-libraries"/>
    <content type="text"><![CDATA[<p><span class="featured">Here&rsquo;s what you need to get started with Telerik Document Processing Libraries to work with PDF, Word and Excel files (and, like any good suite, make all those document types look very much alike).</span></p><p>Progress Telerik Document Processing Libraries, in addition to letting you work with a variety of document formats (PDF, DOCX, RTF, HTML, XLSX and more), are an example of the reason you buy into a suite of tools: All the tools bear a &ldquo;family resemblance.&rdquo;</p><p>The ideal scenario, of course, would be for a single tool that made all these document formats look the same. Given the differences in format and functionality between, for example, a PDF, a Microsoft Word (or RTF or HTML) document and an Excel spreadsheet, that&rsquo;s not reasonable (though Progress Telerik has achieved that with DOCX, RTF and HTML documents).</p><p>The good news here is that, with Telerik Document Processing Libraries (DPL), the family resemblance is strong enough that, for <em>all</em> of the document types the library supports, I can show you how to load documents, start the editing process, convert between various document types and save a document in this one post.</p><h2 id="configuring-your-project">Configuring Your Project</h2><p>The sample code in this post was all written using the DPL for Windows libraries (even though I was working in ASP.NET Core&mdash;the more technical name for the version I used is &ldquo;.NET(Target OS: Windows).&rdquo; The suite is <a target="_blank" href="https://docs.telerik.com/devtools/document-processing/introduction#required-references">also available for the .NET Framework</a>.</p><p>To create an ASP.NET Core project that would work with &ldquo;all the documents,&rdquo; I added these NuGet packages to my project:</p><ul><li>To work with PDF files: Telerik.Windows.Documents.Fixed</li><li>To work with DOCX, HTML and RTF files: Telerik.Windows.Documents.Flow</li><li>To work with Excel spreadsheets: Telerik.Windows.Documents.Spreadsheet</li></ul><p>For the Excel spreadsheets, I&rsquo;m only going to work with XLSX files, so I added the Telerik.Windows.Documents.Spreadsheet.FormatProviders.OpenXml package to my project. (If I was going to work with, for example, XLS spreadsheet, then I would have added the Telerik.Documents.Spreadsheet.FormatProviders.Xls package.)</p><h2 id="loading-your-document">Loading Your Document</h2><p>The code to load a document from a file into any of these libraries is very similar:</p><ol><li>Create the appropriate provider.</li><li>Use the .NET<code>File</code> object&rsquo;s <code>OpenRead</code> to create a <code>Stream</code> that points to the file.</li><li>Use the provider&rsquo;s <code>Import</code> method to load the stream into the document object.</li></ol><p>Here, for example, is the code to load a PDF file into a <code>RadFixedDocument</code> object (I used this code in an ASP.NET Core application with documents in my project&rsquo;s wwwroot folder):</p><pre class=" language-csharp"><code class="prism  language-csharp">RadFixedDocument doc<span class="token punctuation">;</span>
PdfFormatProvider prov <span class="token operator">=</span> <span class="token keyword">new</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">using</span> <span class="token punctuation">(</span>Stream str <span class="token operator">=</span> File<span class="token punctuation">.</span><span class="token function">OpenRead</span><span class="token punctuation">(</span><span class="token string">@"wwwroot/documents/Priorities.pdf"</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
    doc <span class="token operator">=</span> prov<span class="token punctuation">.</span><span class="token function">Import</span><span class="token punctuation">(</span>str<span class="token punctuation">,</span> TimeSpan<span class="token punctuation">.</span><span class="token function">FromSeconds</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><p>And here&rsquo;s the code to load a DOCX file into a <code>RadFlowDocument</code>:</p><pre class=" language-c"><code class="prism # language-c">RadFlowDocument doc<span class="token punctuation">;</span>
DocxFormatProvider prov <span class="token operator">=</span> <span class="token function">new</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token function">using</span> <span class="token punctuation">(</span>Stream str <span class="token operator">=</span> File<span class="token punctuation">.</span><span class="token function">OpenRead</span><span class="token punctuation">(</span>@<span class="token string">"wwwroot/documents/Priorities.docx"</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
    doc <span class="token operator">=</span> prov<span class="token punctuation">.</span><span class="token function">Import</span><span class="token punctuation">(</span>str<span class="token punctuation">,</span> TimeSpan<span class="token punctuation">.</span><span class="token function">FromSeconds</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><p>As you can see, the code is identical except for the provider (<code>PdfFormatProvider</code> vs. <code>DocxFormatProvider</code>) and document objects (<code>RadFlowDocument</code> vs. <code>RadFixedDocument</code>).</p><p>Because both RTF and HTML documents load into the same <code>RadFlowDocument</code> object as a DOCX document, only the provider object changes (<code>HtmlFormatProvider</code> or <code>RtfFormatProdiver</code> instead of <code>DocxFormatProvider</code>) when working with those file formats. Here&rsquo;s the code to load an RTF document:</p><pre class=" language-csharp"><code class="prism  language-csharp">RadFlowDocument doc<span class="token punctuation">;</span>
RtfFormatProvider prov <span class="token operator">=</span> <span class="token keyword">new</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">using</span> <span class="token punctuation">(</span>Stream str <span class="token operator">=</span> File<span class="token punctuation">.</span><span class="token function">OpenRead</span><span class="token punctuation">(</span><span class="token string">@"wwwroot/documents/Priorities.rtf"</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
    doc <span class="token operator">=</span> prov<span class="token punctuation">.</span><span class="token function">Import</span><span class="token punctuation">(</span>str<span class="token punctuation">,</span> TimeSpan<span class="token punctuation">.</span><span class="token function">FromSeconds</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><p>And here&rsquo;s the almost identical code to load an HTML file:</p><pre class=" language-csharp"><code class="prism  language-csharp">RadFlowDocument doc<span class="token punctuation">;</span>
HtmlFormatProvider prov <span class="token operator">=</span> <span class="token keyword">new</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">using</span> <span class="token punctuation">(</span>Stream str <span class="token operator">=</span> File<span class="token punctuation">.</span><span class="token function">OpenRead</span><span class="token punctuation">(</span><span class="token string">@"wwwroot/documents/Priorities.html"</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
    doc <span class="token operator">=</span> prov<span class="token punctuation">.</span><span class="token function">Import</span><span class="token punctuation">(</span>str<span class="token punctuation">,</span> TimeSpan<span class="token punctuation">.</span><span class="token function">FromSeconds</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><p>The code to load an Excel workbook is also similar to what you&rsquo;ve seen before, just swapping in a new document object (<code>Workbook</code>) and provider (<code>XlsxFormatProvider</code>):</p><pre class=" language-csharp"><code class="prism  language-csharp">Workbook doc<span class="token punctuation">;</span>
XlsxFormatProvider prov <span class="token operator">=</span> <span class="token keyword">new</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">using</span> <span class="token punctuation">(</span>Stream str <span class="token operator">=</span> File<span class="token punctuation">.</span><span class="token function">OpenRead</span><span class="token punctuation">(</span><span class="token string">@"wwwroot/documents/priority.xlsx"</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
    doc <span class="token operator">=</span> prov<span class="token punctuation">.</span><span class="token function">Import</span><span class="token punctuation">(</span>str<span class="token punctuation">,</span> TimeSpan<span class="token punctuation">.</span><span class="token function">FromSeconds</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><p>A note: The Workbook object assumes that you&rsquo;re going to load the <em>whole</em> Excel workbook into memory. For very large workbooks, that may not make sense. For that scenario, you should look at the <a target="_blank" href="https://docs.telerik.com/devtools/document-processing/libraries/radspreadstreamprocessing/overview">SpreadStreamProcessing Library</a>.</p><h2 id="modifying-the-documents">Modifying the Documents</h2><p>Once you&rsquo;ve loaded the documents, you can start working with them. You can often simplify your code by using the <code>RadFixedDocumentEditor</code> with PDF documents or the <code>RadFlowDocumentEditor</code>with Word/RTF/HTML documents. Not surprisingly, the code for creating an editor is almost identical for these two document types: create an editor object and pass the document you want loaded into the editor.</p><p>The code to create an editor for a PDF document looks like this:</p><pre class=" language-csharp"><code class="prism  language-csharp">RadFixedDocumentEditor editor <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">RadFixedDocumentEditor</span><span class="token punctuation">(</span>doc<span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre><p>The code for Word/RTF/HTML documents looks like this:</p><pre class=" language-csharp"><code class="prism  language-csharp">RadFlowDocumentEditor editor <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">RadFlowDocumentEditor</span><span class="token punctuation">(</span>doc<span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre><p>That&rsquo;s not to say that, as you start working with those documents, there aren&rsquo;t going to be differences. These are, after all, very different kinds of documents. Having said that, some functionality does work in a similar way across all the document types.</p><p>If, for example, I want to search a PDF document for the text &ldquo;ASP.NET,&rdquo; I create a <code>TextSearch</code> instance from my document object. I then use the <code>TextSearch</code> object&rsquo;s <code>FindAll</code> method to search for text in my PDF document, passing two things: my search text and a <code>TextSearchOptions</code> object that specifies how I want my search conducted. That <code>FindAll</code> object returns a collection of <code>SearchResult</code> objects that I can loop through.</p><p>Typical code, then, looks like this:</p><pre class=" language-csharp"><code class="prism  language-csharp">TextSearch search <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">TextSearch</span><span class="token punctuation">(</span>doc<span class="token punctuation">)</span><span class="token punctuation">;</span>
TextSearchOptions opts <span class="token operator">=</span> <span class="token keyword">new</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
CaseSensitive <span class="token operator">=</span> <span class="token keyword">false</span><span class="token punctuation">,</span>
WholeWordsOnly <span class="token operator">=</span> <span class="token keyword">true</span><span class="token punctuation">,</span>
UseRegularExpression <span class="token operator">=</span> <span class="token keyword">true</span>
                                                              <span class="token punctuation">}</span><span class="token punctuation">;</span>

IEnumerable<span class="token operator">&lt;</span>SearchResult<span class="token operator">&gt;</span> items <span class="token operator">=</span> search<span class="token punctuation">.</span><span class="token function">FindAll</span><span class="token punctuation">(</span><span class="token string">"ASP.NET"</span><span class="token punctuation">,</span> opts<span class="token punctuation">)</span><span class="token punctuation">;</span>

Debug<span class="token punctuation">.</span><span class="token function">Print</span><span class="token punctuation">(</span>$<span class="token string">"Found {items.Count()} items."</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">foreach</span> <span class="token punctuation">(</span>SearchResult item <span class="token keyword">in</span> items<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
    Debug<span class="token punctuation">.</span><span class="token function">Print</span><span class="token punctuation">(</span>$<span class="token string">"Found at {item.Range.StartPosition} "</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    Debug<span class="token punctuation">.</span><span class="token function">Print</span><span class="token punctuation">(</span>$<span class="token string">"Found: {item.Result}"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><p>The process is almost identical for the <code>RadFlowDocument</code> object, except:</p><ul><li>You call the <code>FindAll</code>method directly from the <code>RadFlowDocumentEditor</code>.</li><li>There isn&rsquo;t a separate options object (though all the search options from the <code>TextSearch</code> object are still available).</li><li>The <code>FindAll</code> method on the editor returns <code>FindResult</code> objects instead of <code>SearchResult</code> objects.</li></ul><p>As a result, the equivalent search code for a DOCX, RTF or HTML document looks like this:</p><pre class=" language-csharp"><code class="prism  language-csharp">RadFlowDocumentEditor editor <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">RadFlowDocumentEditor</span><span class="token punctuation">(</span>doc<span class="token punctuation">)</span><span class="token punctuation">;</span>

IEnumerable<span class="token operator">&lt;</span>FindResult<span class="token operator">&gt;</span> items <span class="token operator">=</span> editor<span class="token punctuation">.</span><span class="token function">FindAll</span><span class="token punctuation">(</span><span class="token string">"ASP.NET"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

Debug<span class="token punctuation">.</span><span class="token function">Print</span><span class="token punctuation">(</span>$<span class="token string">"Found {items.Count()} items."</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">foreach</span> <span class="token punctuation">(</span>FindResult item <span class="token keyword">in</span> items<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
    Debug<span class="token punctuation">.</span><span class="token function">Print</span><span class="token punctuation">(</span>$<span class="token string">"Found at {item.RelativeStartIndex} "</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    Debug<span class="token punctuation">.</span><span class="token function">Print</span><span class="token punctuation">(</span>$<span class="token string">"Found: {item.FullMatchText}"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><p>Searching a spreadsheet works similarly. The differences:</p><ul><li>The <code>FindAll</code> method is built right into the <code>Workbook</code> object.</li><li>You have more search options available with the spreadsheet object.</li><li>You pass your search string as part of the options object.</li></ul><p>My find code with a workbook would look like this:</p><pre class=" language-csharp"><code class="prism  language-csharp">FindOptions opts <span class="token operator">=</span> <span class="token keyword">new</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
FindWhat <span class="token operator">=</span> <span class="token string">"ASP.NET"</span><span class="token punctuation">,</span>
MatchCase <span class="token operator">=</span> <span class="token keyword">false</span><span class="token punctuation">,</span>
MatchEntireCellContents <span class="token operator">=</span> <span class="token keyword">true</span><span class="token punctuation">,</span>
                                                <span class="token punctuation">}</span><span class="token punctuation">;</span>

IEnumerable<span class="token operator">&lt;</span>FindResult<span class="token operator">&gt;</span> items <span class="token operator">=</span> doc<span class="token punctuation">.</span><span class="token function">FindAll</span><span class="token punctuation">(</span>opts<span class="token punctuation">)</span><span class="token punctuation">;</span>

Debug<span class="token punctuation">.</span><span class="token function">Print</span><span class="token punctuation">(</span>$<span class="token string">"Found {items.Count()} items."</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">foreach</span><span class="token punctuation">(</span>FindResult item <span class="token keyword">in</span> items<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
    Debug<span class="token punctuation">.</span><span class="token function">Print</span><span class="token punctuation">(</span>$<span class="token string">"Found at {item.FoundCell.CellIndex} "</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    Debug<span class="token punctuation">.</span><span class="token function">Print</span><span class="token punctuation">(</span>$<span class="token string">"Found: {item.ResultValue}"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><p>One note: It is certainly convenient when objects from the different libraries share the same name (like the <code>FindResult</code> object that&rsquo;s defined in both the <code>RadFlowDocument</code> and <code>Workbook</code> libraries). However, if you try to use both <code>FindResult</code> objects in the same code file, the compiler will get confused because the two objects are in different namespaces. In the unlikely case that you&rsquo;re working with both Excel and Word documents in the same code file, you&rsquo;ll have to fully qualify the object names&mdash;something I haven&rsquo;t done in this post.</p><h2 id="saving-your-documents">Saving Your Documents</h2><p>To save your modified documents back to disk, you just need to use the provider&rsquo;s <code>Export</code> method. The code for all the document types is identical:</p><pre class=" language-csharp"><code class="prism  language-csharp"><span class="token keyword">using</span> <span class="token punctuation">(</span>Stream str <span class="token operator">=</span> File<span class="token punctuation">.</span><span class="token function">Create</span><span class="token punctuation">(</span><span class="token string">@"wwwroot/documents/Prioritiesnew.&lt;filetype&gt;"</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
    prov<span class="token punctuation">.</span><span class="token function">Export</span><span class="token punctuation">(</span>doc<span class="token punctuation">,</span>str<span class="token punctuation">,</span> TimeSpan<span class="token punctuation">.</span><span class="token function">FromSeconds</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><h2 id="converting-documents">Converting Documents</h2><p>You can convert from one type in the suite to other types and, not surprisingly, the conversion processes look very much alike. As you&rsquo;ve seen before, it often comes down to using the right provider.</p><p>If, for example, you want plain text version of your PDF file, you use the <code>TextFormatProvider</code> object&rsquo;s <code>Export</code> method:</p><pre class=" language-csharp"><code class="prism  language-csharp">TextFormatProvider prov <span class="token operator">=</span> <span class="token keyword">new</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">string</span> text <span class="token operator">=</span> prov<span class="token punctuation">.</span><span class="token function">Export</span><span class="token punctuation">(</span>doc<span class="token punctuation">,</span> TimeSpan<span class="token punctuation">.</span><span class="token function">FromSeconds</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre><p>For Word/HTML/RTF document types, the code is almost identical except it uses the <code>TxtFormatProvider</code> object:</p><pre class=" language-csharp"><code class="prism  language-csharp">TxtFormatProvider txProv <span class="token operator">=</span> <span class="token keyword">new</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">string</span> text <span class="token operator">=</span> prov<span class="token punctuation">.</span><span class="token function">Export</span><span class="token punctuation">(</span>doc<span class="token punctuation">,</span> TimeSpan<span class="token punctuation">.</span><span class="token function">FromSeconds</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>            
</code></pre><p>One note: There is a downside to having the classes that do similar things to different document types have the same name. If you are mixing document types and, as a result, using the Fixed, Flow and spreadsheet libraries in the same application, the compiler can get confused about which class from which library you&rsquo;re using. If so, you&rsquo;ll have to <a target="_blank" href="https://docs.telerik.com/devtools/document-processing/knowledge-base/cs0104-error-pdf-format-provider">fully qualify your class names</a> by including their namespaces in the class names. That makes for hard-to-read code, so I haven&rsquo;t done that here.</p><p>But, as an example of how different documents require different functionality, you probably wouldn&rsquo;t ever want to convert an Excel workbook to a string &hellip; but you might want to save your workbook as a CSV file. As you might expect by now, the code to save your imported workbook into a CSV file just means using the <code>Export</code> method on the appropriate provider&mdash;the <code>CsvFormatProvider</code> object in this case.</p><p>Typical code would look like this:</p><pre class=" language-csharp"><code class="prism  language-csharp">CsvFormatProvider prov <span class="token operator">=</span> <span class="token keyword">new</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">using</span> <span class="token punctuation">(</span>Stream str <span class="token operator">=</span> File<span class="token punctuation">.</span><span class="token function">Create</span><span class="token punctuation">(</span><span class="token string">"Priority.csv"</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
    prov<span class="token punctuation">.</span><span class="token function">Export</span><span class="token punctuation">(</span>doc<span class="token punctuation">,</span> str<span class="token punctuation">,</span> TimeSpan<span class="token punctuation">.</span><span class="token function">FromSeconds</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><p><a target="_blank" href="https://www.telerik.com/blogs/quick-and-easy-conversion-to-pdf-with-telerik-document-processing-library">Converting any of these document types (Excel, Word, HTML, etc.) to PDF</a> is equally straightforward. Because all the libraries look very much alike, it&rsquo;s really just a matter of adding the library with the provider you need.</p><p>But you can also convert your <code>Workbook</code> object into a <code>RadFixedDocument</code> if you wanted to manipulate your spreadsheet as a PDF object. That conversion is handled by the PdfFormatProvider from the Telerik.Windows.Documents.Spreadsheet.Formatproviders.Pdf package and using its <code>ExportToFixedDocument</code>method:</p><pre class=" language-csharp"><code class="prism  language-csharp">PdfFormatProvider prov <span class="token operator">=</span> <span class="token keyword">new</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

RadFixedDocument fixedDoc <span class="token operator">=</span> 
        prov<span class="token punctuation">.</span><span class="token function">ExportToFixedDocument</span><span class="token punctuation">(</span>doc<span class="token punctuation">,</span> TimeSpan<span class="token punctuation">.</span><span class="token function">FromSeconds</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre><p>The code is identical if you want to convert a Word/RTF/HTML document to a <code>RadFixedDocument</code> to work with it as a PDF file. That conversion also uses a <code>PdfFormatProvider</code> object but, this time, from the Telerik.Windows.Documents.Flow.FormatProviders.Pdf namespace.</p><p>But, because the providers from the two libraries have the same name, if you&rsquo;re using both libraries in the same code file, you will need to fully qualify your provider names to make sure you&rsquo;re getting the appropriate <code>PdfFormatProvider</code>.</p><p>Of course, once you start using these tools to create or modify the documents you&rsquo;ve loaded, you&rsquo;ll find more differences&mdash;the functionality in a spreadsheet is very different from the functionality in an HTML document. But, while the family resemblances among this suite won&rsquo;t eliminate those differences, it does cut those differences down to what matters: how those documents differ in their functionality. Which is, after all, what you want.</p><hr /><p>Explore Telerik Document Processing Libraries, plus component libraries, reporting and more with a free trial of the Telerik DevCraft bundle:</p><p><a href="https://www.telerik.com/download" class="Btn" target="_blank">Try DevCraft</a></p><img src="https://feeds.telerik.com/link/23072/17310582.gif" height="1" width="1"/>]]></content>
  </entry>
  <entry>
    <id>urn:uuid:f3a4d2ee-5d34-4a83-a4de-4e2bf84e0462</id>
    <title type="text">Spreadsheet Analysis with Telerik Document Processing Libraries Agentic Tools</title>
    <summary type="text">Agentic workflows provide dynamic ways to interact with and analyze documents. The Telerik Document Processing Libraries now have these AI tools ready to use!</summary>
    <published>2026-03-04T21:25:50Z</published>
    <updated>2026-04-11T21:18:52Z</updated>
    <author>
      <name>Anna Velcheva </name>
    </author>
    <link rel="alternate" href="https://feeds.telerik.com/link/23072/17293375/spreadsheet-analysis-telerik-document-processing-libraries-agentic-tools"/>
    <content type="text"><![CDATA[<p><span class="featured">Agentic workflows provide dynamic ways to interact with and analyze documents. The Progress Telerik Document Processing Libraries now have these AI tools ready to use!</span></p><p>Modern applications rely on automation and intelligent processing to handle large volumes of data, and spreadsheets are no exception. With the <a target="_blank" href="https://www.telerik.com/blogs/next-productivity-leap-telerik-kendo-ui-2026-q1-release">2026 Q1 release</a>, Progress introduced <a target="_blank" href="https://docs.telerik.com/devtools/document-processing/ai-tools/agent-tools/overview">Agentic Tools (in Preview) for Telerik Document Processing Libraries</a> (DPL).</p><p>These tools are purpose‑built .NET APIs for agentic document workflows, enabling AI agents to analyze, extract, edit and generate Excel and PDF files; run aggregates; transform content; and convert formats directly inside your app. The new Agentic Tools cover both PdfProcessing and <a target="_blank" href="https://demos.telerik.com/document-processing/spreadprocessing/agentic_tools">SpreadProcessing</a> libraries and are available with a Subscription license.</p><p>In this post, we&rsquo;ll walk you through how to use the SpreadProcessing Agentic Tools to analyze an existing spreadsheet.</p><h2 id="importing-the-workbook">Importing the Workbook</h2><p>Let&rsquo;s create a simple .NET console app. Our first step is to import the Workbook. I am going to add the <a target="_blank" href="https://docs.telerik.com/devtools/document-processing/getting-started/first-steps">necessary DPL dependencies</a>, in this case:</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-03/dpl-packages.png?sfvrsn=9294b0de_2" alt="DPL packages: Telerik.Windows.Documents.Spreadsheet and Telerik.Windows.Documents.Spreadsheet.FormatProviders.OpenXml" /></p><p>and then use this code:</p><pre class=" language-csharp"><code class="prism  language-csharp">Workbook workbook <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span>

<span class="token keyword">using</span> <span class="token punctuation">(</span>Stream input <span class="token operator">=</span> File<span class="token punctuation">.</span><span class="token function">OpenRead</span><span class="token punctuation">(</span><span class="token string">"Electric_Vehicle_Population_Data.xlsx"</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
    XlsxFormatProvider formatProvider <span class="token operator">=</span> <span class="token keyword">new</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    workbook <span class="token operator">=</span> formatProvider<span class="token punctuation">.</span><span class="token function">Import</span><span class="token punctuation">(</span>input<span class="token punctuation">,</span> <span class="token keyword">null</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><p>In case you are wondering, this file contains 17 columns and 75,331 rows of data.</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-03/spreadsheet-data-glimpse.png?sfvrsn=3fd645a2_2" alt="Screenshot of a spreadsheet with VIN, County, City, State, Postal Code, Model Year, Make, Model, etc." /></p><p>An agent using the DPL tools can work with multiple files at the same time by importing and exporting them via the <a target="_blank" href="https://docs.telerik.com/devtools/document-processing/ai-tools/agent-tools/spreadsheet-document-api#spreadprocessingfilemanagementagenttools">SpreadProcessingFileManagementAgentTools</a> and managing them with the <a target="_blank" href="https://docs.telerik.com/devtools/document-processing/ai-tools/agent-tools/spreadsheet-document-api#repositories">InMemoryWorkbookRepository</a>. However, in this example we are going to concentrate on analyzing one workbook, so we are going to use the SingleWorkbookRepository, a class which gives an agent a single file to work with in memory.</p><pre class=" language-csharp"><code class="prism  language-csharp">IWorkbookRepository repository <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">SingleWorkbookRepository</span><span class="token punctuation">(</span>workbook<span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre><p>For this code, we need to reference the Telerik.Documents.AI.AgentTools.Spreadsheet package.</p><h2 id="initializing-the-dpl-agentic-tools">Initializing the DPL Agentic Tools</h2><p>Initializing the Agentic Tools is very simple. For this example, we will use an Azure Open AI deployment, so first we are going to add the <a target="_blank" href="https://learn.microsoft.com/en-us/agent-framework/agents/providers/openai?pivots=programming-language-csharp">Microsoft.Agents.AI.OpenAI</a> and Azure.AI.OpenAI packages. Then we are going to collect the Read and Formula tools in one collection:</p><pre class=" language-csharp"><code class="prism  language-csharp">List<span class="token operator">&lt;</span>AITool<span class="token operator">&gt;</span> tools <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">SpreadProcessingReadAgentTools</span><span class="token punctuation">(</span>repository<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">GetTools</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">ToList</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
tools<span class="token punctuation">.</span><span class="token function">AddRange</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">SpreadProcessingFormulaAgentTools</span><span class="token punctuation">(</span>repository<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">GetTools</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre><p>And then we can initialize our agent. We are going to need an Azure Open AI endpoint and key and are going to use gpt-4.1-mini.</p><pre class=" language-csharp"><code class="prism  language-csharp">OpenAI<span class="token punctuation">.</span>Chat<span class="token punctuation">.</span>ChatClient chatClient <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">AzureOpenAIClient</span><span class="token punctuation">(</span>
    <span class="token keyword">new</span> <span class="token class-name">Uri</span><span class="token punctuation">(</span>endpoint<span class="token punctuation">)</span><span class="token punctuation">,</span>
    <span class="token keyword">new</span> <span class="token class-name">ApiKeyCredential</span><span class="token punctuation">(</span>key<span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token punctuation">.</span><span class="token function">GetChatClient</span><span class="token punctuation">(</span>model<span class="token punctuation">)</span><span class="token punctuation">;</span>

AIAgent agent <span class="token operator">=</span> chatClient<span class="token punctuation">.</span><span class="token function">AsIChatClient</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">AsAIAgent</span><span class="token punctuation">(</span>
    instructions<span class="token punctuation">:</span> <span class="token string">""</span><span class="token punctuation">,</span>
    name<span class="token punctuation">:</span> <span class="token string">"SpreadsheetAnalyzer"</span><span class="token punctuation">,</span>
    tools<span class="token punctuation">:</span> tools<span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre><p>At this point, we can already ask a simple question to check our progress:</p><pre class=" language-csharp"><code class="prism  language-csharp">AgentResponse response <span class="token operator">=</span> <span class="token keyword">await</span> agent<span class="token punctuation">.</span><span class="token function">RunAsync</span><span class="token punctuation">(</span><span class="token string">"What is the value on cell A4?"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
Console<span class="token punctuation">.</span><span class="token function">WriteLine</span><span class="token punctuation">(</span>response<span class="token punctuation">.</span><span class="token function">ToString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre><p>Here is the result:</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-03/dpl-question-answered.png?sfvrsn=f1f9444b_2" alt="Window shows text: The value in cell A4 is… Is there anything else you would like to know" /></p><p>If you examine the response of the agent more closely, you will notice that it contains three messages. The first is the function call the agent made to the document processing tool GetCellValues and with what parameters. The second is the response. And the third is what the LLM has reasoned and has decided to give us.</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-03/dpl-ai-response-messages.png?sfvrsn=5100adde_2" alt="More insight into the DPL AI Agent response" /></p><h2 id="giving-it-ui">Giving It UI</h2><p>A console app is good for a proof of concept, but it would be nice to give our functionality a more finished look. One of the ways to do this is by using some Progress <a target="_blank" href="https://www.telerik.com/products/wpf/overview.aspx">Telerik for WPF</a> controls. The RadSpreadsheet control can show the content of our file, and we can leverage RadChat for the conversation with the agent.</p><p>We can give the repository the Workbook object of the RadSpreadsheet like this when initializing the chat:</p><pre class=" language-csharp"><code class="prism  language-csharp">IWorkbookRepository repository <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">SingleWorkbookRepository</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>radSpreadsheet<span class="token punctuation">.</span>Workbook<span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre><p>Then we are going to subscribe to the SendMessage event, which is where our logic for running the agent is going to go:</p><pre class=" language-csharp"><code class="prism  language-csharp"><span class="token keyword">this</span><span class="token punctuation">.</span>radChat<span class="token punctuation">.</span>SendMessage <span class="token operator">+</span><span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>RadChat_SendMessage<span class="token punctuation">;</span>
</code></pre><p>After a few more tweaks, this is the result:</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2026/2026-03/spreadsheet-ai-agent-initialized.png?sfvrsn=3e11626f_2" alt="Spredsheet with right panel showing the AI Assistant, with AI agent initialized and ready to help with your spreadsheet!" /></p><p>The full code of the demo can be found on this link: <a target="_blank" href="https://github.com/telerik/document-processing-sdk/tree/master/AITools/AgentToolsAnalyzeSpreadsheet">AgentToolsAnalyzeSpreadsheet on GitHub</a></p><h2 id="conclusion">Conclusion</h2><p>Agentic workflows introduce a powerful new way to interact with documents, moving beyond static reading and writing to dynamic, intelligent analysis. As you&rsquo;ve seen, the setup integrates seamlessly with .NET, and, once the agent is initialized, it can leverage the full capabilities of the Document Processing Libraries.</p><p>This example is just the beginning! The same approach can be extended to multi-document scenarios, automated reporting, data validation or even generating new spreadsheets from scratch.</p><p>The future of document processing is agentic, and it&rsquo;s already here.</p><hr /><blockquote><p>Try out the <a target="_blank" href="https://www.telerik.com/document-processing-libraries">Telerik Document Processing Libraries</a>, which are included in the <a target="_blank" href="https://www.telerik.com/devcraft">Telerik DevCraft bundles</a> to pair perfectly with your favorite component libraries.</p><br /><a target="_blank" href="https://www.telerik.com/try/devcraft-ultimate" class="Btn">Try Telerik DevCraft</a>
</blockquote><img src="https://feeds.telerik.com/link/23072/17293375.gif" height="1" width="1"/>]]></content>
  </entry>
  <entry>
    <id>urn:uuid:034079bc-0ee8-42e4-a55e-9e6d40c6e8c0</id>
    <title type="text">Cloud Integration with Telerik Document Processing</title>
    <summary type="text">Learn how to integrate Telerik Document Processing with Azure and AWS cloud services, including all the PDF processing you’ll need in a serverless environment.</summary>
    <published>2025-12-17T13:04:00Z</published>
    <updated>2026-04-11T21:18:52Z</updated>
    <author>
      <name>Desislava Yordanova </name>
    </author>
    <link rel="alternate" href="https://feeds.telerik.com/link/23072/17248733/cloud-integration-telerik-document-processing"/>
    <content type="text"><![CDATA[<p><span class="featured">Learn how to integrate Telerik Document Processing with Azure and AWS cloud services, including all the PDF processing you&rsquo;ll need in a serverless environment.</span></p><p>Offloading document generation, conversion or manipulation to cloud services allows you to handle large workloads without overloading on-prem resources. Azure Functions and AWS Lambda scale automatically based on demand, so whether you need to generate 10 or 10,000 documents, the infrastructure adjusts dynamically. Serverless models charge per execution time and resources consumed, eliminating the need for dedicated servers for document processing. Thus, you pay only for what you use.</p><p>This blog post introduces comprehensive cloud integration demonstrations for Azure and AWS, showcasing PDF processing capabilities using Progress&nbsp;<a target="_blank" href="https://docs.telerik.com/devtools/document-processing/introduction">Telerik Document Processing</a> in serverless environments. The examples demonstrate two main integration patterns: PDF merging and external digital signing, implemented for both Azure Functions and AWS Lambda. The complete code projects are available in our SDK repository: <a target="_blank" href="https://github.com/telerik/document-processing-sdk/tree/master/CloudIntegration">Cloud Integration Demos</a>.</p><h2 id="integrate-radpdfprocessing-with-azure-functions">Integrate RadPdfProcessing with Azure Functions</h2><p>First, you&rsquo;ll need: an active <a target="_blank" href="https://azure.microsoft.com/en-us">Azure subscription</a>, <a target="_blank" href="https://learn.microsoft.com/en-us/azure/azure-functions/functions-run-local?tabs=windows%2Cisolated-process%2Cnode-v4%2Cpython-v2%2Chttp-trigger%2Ccontainer-apps&amp;pivots=programming-language-csharp">Azure functions tools</a> installed and the <a target="_blank" href="https://docs.telerik.com/devtools/document-processing/getting-started/installation/install-nuget-packages#download-from-the-nuget-server">Telerik NuGet feed</a> set up.</p><ol><li>Create an Azure Functions App</li></ol><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2025/2025-12/azure-functions-app.png?sfvrsn=f131fb5c_2" alt="Create a new project: Azure functions" /></p><ol start="2"><li>Select <em>Anonymous</em> <strong>authorization level</strong>:</li></ol><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2025/2025-12/anonymous-authorization.png?sfvrsn=aafe94b9_2" alt="Additional information – Azure Functions – Authorization level: Anonymous" /></p><ol start="3"><li>Install the following NuGet packages:</li></ol><ul><li>Install the <a target="_blank" href="https://docs.telerik.com/devtools/document-processing/libraries/radpdfprocessing/getting-started">Telerik.Documents.Fixed</a> NuGet package.</li><li>Install the <a target="_blank" href="https://www.nuget.org/packages/HttpMultipartParser">HttpMultipartParser</a> NuGet package:</li></ul><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2025/2025-12/httpmultipartparser-nuget.png?sfvrsn=e85a6b87_2" alt="NuGet Package Manager: HttpMultipartParser" /></p><ol start="4"><li>Rename the Functiona1.cs file to &ldquo;MergeFunction&rdquo; and introduce your custom implementation in the <strong>Run</strong> method:</li></ol><pre class=" language-csharp"><code class="prism  language-csharp"><span class="token keyword">using</span> HttpMultipartParser<span class="token punctuation">;</span>
<span class="token keyword">using</span> Microsoft<span class="token punctuation">.</span>Azure<span class="token punctuation">.</span>Functions<span class="token punctuation">.</span>Worker<span class="token punctuation">;</span>
<span class="token keyword">using</span> Microsoft<span class="token punctuation">.</span>Azure<span class="token punctuation">.</span>Functions<span class="token punctuation">.</span>Worker<span class="token punctuation">.</span>Http<span class="token punctuation">;</span>
<span class="token keyword">using</span> System<span class="token punctuation">.</span>Net<span class="token punctuation">;</span>
<span class="token keyword">using</span> Telerik<span class="token punctuation">.</span>Windows<span class="token punctuation">.</span>Documents<span class="token punctuation">.</span>Fixed<span class="token punctuation">.</span>FormatProviders<span class="token punctuation">.</span>Pdf<span class="token punctuation">;</span>
<span class="token keyword">using</span> Telerik<span class="token punctuation">.</span>Windows<span class="token punctuation">.</span>Documents<span class="token punctuation">.</span>Fixed<span class="token punctuation">.</span>Model<span class="token punctuation">;</span>
 
<span class="token keyword">namespace</span> MyAzureFunctionApp<span class="token punctuation">;</span>
 
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">MergeFunction</span>
<span class="token punctuation">{</span>
    <span class="token punctuation">[</span><span class="token function">Function</span><span class="token punctuation">(</span><span class="token string">"MergeFunction"</span><span class="token punctuation">)</span><span class="token punctuation">]</span>
    <span class="token keyword">public</span> <span class="token keyword">async</span> Task<span class="token operator">&lt;</span>HttpResponseData<span class="token operator">&gt;</span> <span class="token function">Run</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token function">HttpTrigger</span><span class="token punctuation">(</span>AuthorizationLevel<span class="token punctuation">.</span>Anonymous<span class="token punctuation">,</span> <span class="token string">"get"</span><span class="token punctuation">,</span> <span class="token string">"post"</span><span class="token punctuation">)</span><span class="token punctuation">]</span> HttpRequestData req<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        Task<span class="token operator">&lt;</span>MultipartFormDataParser<span class="token operator">&gt;</span> parsedFormBody <span class="token operator">=</span> MultipartFormDataParser<span class="token punctuation">.</span><span class="token function">ParseAsync</span><span class="token punctuation">(</span>req<span class="token punctuation">.</span>Body<span class="token punctuation">)</span><span class="token punctuation">;</span>
 
        PdfFormatProvider provider <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">PdfFormatProvider</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        RadFixedDocument result <span class="token operator">=</span> <span class="token function">MergePdfs</span><span class="token punctuation">(</span>provider<span class="token punctuation">,</span> parsedFormBody<span class="token punctuation">.</span>Result<span class="token punctuation">.</span>Files<span class="token punctuation">)</span><span class="token punctuation">;</span>
 
        <span class="token keyword">using</span> <span class="token punctuation">(</span>MemoryStream outputStream <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">MemoryStream</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
        <span class="token punctuation">{</span>
            provider<span class="token punctuation">.</span><span class="token function">Export</span><span class="token punctuation">(</span>result<span class="token punctuation">,</span> outputStream<span class="token punctuation">,</span> TimeSpan<span class="token punctuation">.</span><span class="token function">FromSeconds</span><span class="token punctuation">(</span><span class="token number">20</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            outputStream<span class="token punctuation">.</span><span class="token function">Seek</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> SeekOrigin<span class="token punctuation">.</span>Begin<span class="token punctuation">)</span><span class="token punctuation">;</span>
 
            HttpResponseData httpResponseData <span class="token operator">=</span> req<span class="token punctuation">.</span><span class="token function">CreateResponse</span><span class="token punctuation">(</span>HttpStatusCode<span class="token punctuation">.</span>OK<span class="token punctuation">)</span><span class="token punctuation">;</span>
            httpResponseData<span class="token punctuation">.</span>Headers<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token string">"Content-Type"</span><span class="token punctuation">,</span> <span class="token string">"application/pdf"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">await</span> outputStream<span class="token punctuation">.</span><span class="token function">CopyToAsync</span><span class="token punctuation">(</span>httpResponseData<span class="token punctuation">.</span>Body<span class="token punctuation">)</span><span class="token punctuation">;</span>
 
            <span class="token keyword">return</span> httpResponseData<span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
 
    <span class="token keyword">static</span> RadFixedDocument <span class="token function">MergePdfs</span><span class="token punctuation">(</span>PdfFormatProvider pdfFormatProvider<span class="token punctuation">,</span> IReadOnlyList<span class="token operator">&lt;</span>FilePart<span class="token operator">&gt;</span> files<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        RadFixedDocument mergedDocument <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">RadFixedDocument</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">foreach</span> <span class="token punctuation">(</span>FilePart file <span class="token keyword">in</span> files<span class="token punctuation">)</span>
        <span class="token punctuation">{</span>
            RadFixedDocument documentToMerge <span class="token operator">=</span> pdfFormatProvider<span class="token punctuation">.</span><span class="token function">Import</span><span class="token punctuation">(</span>file<span class="token punctuation">.</span>Data<span class="token punctuation">,</span> TimeSpan<span class="token punctuation">.</span><span class="token function">FromSeconds</span><span class="token punctuation">(</span><span class="token number">20</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            mergedDocument<span class="token punctuation">.</span><span class="token function">Merge</span><span class="token punctuation">(</span>documentToMerge<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
 
        <span class="token keyword">return</span> mergedDocument<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span> 
</code></pre><p>This Azure Function, named <code>MergeFunction</code>, handles HTTP GET and POST requests to merge multiple PDF files into a single document. It uses:</p><ul><li><strong>HttpMultipartParser</strong> to parse multipart form data and extract uploaded files.</li><li>Telerik PdfFormatProvider and RadFixedDocument to import and merge PDF documents.</li><li>The merged PDF is exported to a memory stream and returned as an HTTP response with the application/pdf content type.</li></ul><p>The function supports anonymous access and processes uploaded files efficiently, so that the merged PDF is delivered in the response. Since the function is implemented with anonymous access for demo purposes, consider adding authentication as needed for your scenario.</p><ol start="5"><li>Run the project and copy the URL from the window that pops up:</li></ol><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2025/2025-12/mergefunction-get-post-url.png?sfvrsn=fe127b29_2" alt="MergeFunction GET, POST url" /></p><ol start="6"><li>Create a .NET Console App (e.g., MyMergeApp) that acts as a client for the Azure Function PDF Merge service.</li></ol><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2025/2025-12/console-app.png?sfvrsn=8d50fc5f_2" alt="Add a new project – Console App" /></p><pre class=" language-csharp"><code class="prism  language-csharp"><span class="token keyword">using</span> System<span class="token punctuation">.</span>Diagnostics<span class="token punctuation">;</span>
<span class="token keyword">using</span> System<span class="token punctuation">.</span>Net<span class="token punctuation">.</span>Http<span class="token punctuation">.</span>Headers<span class="token punctuation">;</span>
 
<span class="token keyword">namespace</span> MyMergeApp
<span class="token punctuation">{</span>
    <span class="token keyword">internal</span> <span class="token keyword">class</span> <span class="token class-name">Program</span>
    <span class="token punctuation">{</span>
        <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">Main</span><span class="token punctuation">(</span><span class="token keyword">string</span><span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span>
        <span class="token punctuation">{</span>
            <span class="token keyword">string</span> functionUrl <span class="token operator">=</span> <span class="token string">"http://localhost:7163/api/MergeFunction"</span><span class="token punctuation">;</span>
 
            <span class="token comment">// Specify PDF files to merge from the Resources directory</span>
            <span class="token keyword">string</span><span class="token punctuation">[</span><span class="token punctuation">]</span> pdfFilePaths <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token string">"../../../Resources/file1.pdf"</span><span class="token punctuation">,</span> <span class="token string">"../../../Resources/file2.pdf"</span> <span class="token punctuation">}</span><span class="token punctuation">;</span>
 
            <span class="token comment">// Create multipart form data content for file upload</span>
            <span class="token keyword">using</span> MultipartFormDataContent content <span class="token operator">=</span> <span class="token keyword">new</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 
            <span class="token comment">// Add each PDF file to the form data</span>
            <span class="token keyword">foreach</span> <span class="token punctuation">(</span><span class="token keyword">string</span> filePath <span class="token keyword">in</span> pdfFilePaths<span class="token punctuation">)</span>
            <span class="token punctuation">{</span>
                <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> fileBytes <span class="token operator">=</span> File<span class="token punctuation">.</span><span class="token function">ReadAllBytes</span><span class="token punctuation">(</span>filePath<span class="token punctuation">)</span><span class="token punctuation">;</span>
                ByteArrayContent fileContent <span class="token operator">=</span> <span class="token keyword">new</span><span class="token punctuation">(</span>fileBytes<span class="token punctuation">)</span><span class="token punctuation">;</span>
                fileContent<span class="token punctuation">.</span>Headers<span class="token punctuation">.</span>ContentType <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">MediaTypeHeaderValue</span><span class="token punctuation">(</span><span class="token string">"application/pdf"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                content<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span>fileContent<span class="token punctuation">,</span> <span class="token string">"files"</span><span class="token punctuation">,</span> Path<span class="token punctuation">.</span><span class="token function">GetFileName</span><span class="token punctuation">(</span>filePath<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">}</span>
 
            <span class="token comment">// Send the merge request to the Azure Function</span>
            HttpResponseMessage response <span class="token operator">=</span> <span class="token function">PostAsync</span><span class="token punctuation">(</span>functionUrl<span class="token punctuation">,</span> content<span class="token punctuation">)</span><span class="token punctuation">.</span>Result<span class="token punctuation">;</span>
            response<span class="token punctuation">.</span><span class="token function">EnsureSuccessStatusCode</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 
            <span class="token comment">// Read the merged PDF from the response</span>
            <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> result <span class="token operator">=</span> response<span class="token punctuation">.</span>Content<span class="token punctuation">.</span><span class="token function">ReadAsByteArrayAsync</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span>Result<span class="token punctuation">;</span>
 
            <span class="token comment">// Save the merged PDF to disk</span>
            <span class="token keyword">string</span> outputPath <span class="token operator">=</span> <span class="token string">"merged_output.pdf"</span><span class="token punctuation">;</span>
            <span class="token keyword">if</span> <span class="token punctuation">(</span>File<span class="token punctuation">.</span><span class="token function">Exists</span><span class="token punctuation">(</span>outputPath<span class="token punctuation">)</span><span class="token punctuation">)</span>
            <span class="token punctuation">{</span>
                File<span class="token punctuation">.</span><span class="token function">Delete</span><span class="token punctuation">(</span>outputPath<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">}</span>
            File<span class="token punctuation">.</span><span class="token function">WriteAllBytes</span><span class="token punctuation">(</span>outputPath<span class="token punctuation">,</span> result<span class="token punctuation">)</span><span class="token punctuation">;</span>
 
            <span class="token comment">// Open the merged PDF in the default viewer</span>
            Process<span class="token punctuation">.</span><span class="token function">Start</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">ProcessStartInfo</span><span class="token punctuation">(</span>outputPath<span class="token punctuation">)</span> <span class="token punctuation">{</span> UseShellExecute <span class="token operator">=</span> <span class="token keyword">true</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
        <span class="token keyword">static</span> <span class="token keyword">async</span> Task<span class="token operator">&lt;</span>HttpResponseMessage<span class="token operator">&gt;</span> <span class="token function">PostAsync</span><span class="token punctuation">(</span><span class="token keyword">string</span> url<span class="token punctuation">,</span> MultipartFormDataContent content<span class="token punctuation">)</span>
        <span class="token punctuation">{</span>
            <span class="token keyword">using</span> HttpClient httpClient <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">HttpClient</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            httpClient<span class="token punctuation">.</span>Timeout <span class="token operator">=</span> TimeSpan<span class="token punctuation">.</span><span class="token function">FromMinutes</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Allow sufficient time for large files</span>
 
            <span class="token keyword">return</span> <span class="token keyword">await</span> httpClient<span class="token punctuation">.</span><span class="token function">PostAsync</span><span class="token punctuation">(</span>url<span class="token punctuation">,</span> content<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><p>It demonstrates how to send multiple PDF files to the MergeFunction endpoint and handle the merged result. The workflow includes:</p><ul><li>Loading PDF files from a local <strong>Resources</strong> directory.</li><li>Packaging the files as multipart form data for upload.</li><li>Sending an HTTP POST request to the Azure Function endpoint.</li><li>Receiving the merged PDF in the response and saving it to disk.</li><li>Automatically opening the merged PDF in the system&rsquo;s default viewer.<br />The application uses HttpClient for communication, enables proper content type headers and includes a helper method <code>PostAsync</code> for sending requests with a configurable timeout.</li></ul><ol start="7"><li>Run the Azure Functions .NET Worker (e.g., MyAzureFunctionApp.csproj):</li></ol><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2025/2025-12/run-azure-function-net-worker.png?sfvrsn=8d5b5cd1_2" alt="Run the Azure Functions .NET Worker" /></p><ol start="8"><li>While the service is running, run the Console App (e.g., MyMergeApp).</li></ol><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2025/2025-12/run-console-app.png?sfvrsn=95348a8_2" alt="Running the MyMergeApp console app" /></p><p>As a result, a merged PDF document will be produced:</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2025/2025-12/merged-pdf.png?sfvrsn=a29eb92e_2" alt="Merged PDF" /></p><h2 id="integrate-radpdfprocessing-with-aws-lambda">Integrate RadPdfProcessing with AWS Lambda</h2><p>Using an AWS Lambda function for signing PDF documents offers a more secure, scalable and cost-effective approach to digital signature workflows. By offloading the signing process to a serverless environment, sensitive private keys remain isolated in the cloud, reducing the risk of exposure on client machines.</p><p>The following tutorial defines the steps for creating an AWS Lambda function that performs digital signature operations for PDF documents using a private key stored in a certificate file. The AWS Lambda function is purposed to act as a more secure service that remotely signs PDF documents, and the private key is never exposed to the client.</p><p>Before starting, you&rsquo;ll need valid <a target="_blank" href="https://docs.aws.amazon.com/toolkit-for-visual-studio/latest/user-guide/keys-profiles-credentials.html">AWS Credentials</a> and the <a target="_blank" href="https://docs.telerik.com/devtools/document-processing/getting-started/installation/telerik-nuget-source">Telerik NuGet Feed</a> properly set up.</p><ol><li>Create AWS Lambda Project (e.g., MyAWSLambda):</li></ol><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2025/2025-12/lambda-project.png?sfvrsn=cb93aa7a_2" alt="Create a new project – Lambda Project" /></p><ol start="2"><li>From the <em>Select Blueprint</em> wizard, select &ldquo;.NET 8 (Container Image)&rdquo;:</li></ol><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2025/2025-12/net-8-container-image.png?sfvrsn=8f55eed6_2" alt="AWS Select Blueprint - .NET 8 (Container Image)" /></p><ol start="3"><li>Open the Function.cs file and implement the custom logic for signing PDF documents in the FunctionHandler:</li></ol><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2025/2025-12/lambda-function.png?sfvrsn=b8dd76f_2" alt="MyAWSLambda – Function.cs" /></p><p>The method receives data to be signed, signs it using a <strong>private</strong> key certificate, and returns the Base64-encoded signature. The .pfx certificate is stored independently from the project used for processing documents.</p><p>NOTE: Do not forget that sensitive data should be stored properly and that this implementation is for demo purposes.</p><pre class=" language-csharp"><code class="prism  language-csharp"><span class="token keyword">using</span> Amazon<span class="token punctuation">.</span>Lambda<span class="token punctuation">.</span>Core<span class="token punctuation">;</span>
<span class="token keyword">using</span> System<span class="token punctuation">.</span>Security<span class="token punctuation">.</span>Cryptography<span class="token punctuation">;</span>
<span class="token keyword">using</span> System<span class="token punctuation">.</span>Security<span class="token punctuation">.</span>Cryptography<span class="token punctuation">.</span>X509Certificates<span class="token punctuation">;</span>
 
<span class="token comment">// Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.</span>
<span class="token punctuation">[</span>assembly<span class="token punctuation">:</span> <span class="token function">LambdaSerializer</span><span class="token punctuation">(</span><span class="token keyword">typeof</span><span class="token punctuation">(</span>Amazon<span class="token punctuation">.</span>Lambda<span class="token punctuation">.</span>Serialization<span class="token punctuation">.</span>SystemTextJson<span class="token punctuation">.</span>DefaultLambdaJsonSerializer<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">]</span>
 
<span class="token keyword">namespace</span> MyAWSLambda<span class="token punctuation">;</span>
 
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Function</span>
<span class="token punctuation">{</span>
    <span class="token keyword">public</span> <span class="token keyword">async</span> Task<span class="token operator">&lt;</span><span class="token keyword">string</span><span class="token operator">&gt;</span> <span class="token function">FunctionHandler</span><span class="token punctuation">(</span>Input input<span class="token punctuation">,</span> ILambdaContext context<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> dataToSign <span class="token operator">=</span> Convert<span class="token punctuation">.</span><span class="token function">FromBase64String</span><span class="token punctuation">(</span>input<span class="token punctuation">.</span>DataToSign<span class="token punctuation">)</span><span class="token punctuation">;</span>
 
        <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token operator">?</span> result <span class="token operator">=</span> <span class="token function">SignData</span><span class="token punctuation">(</span>dataToSign<span class="token punctuation">,</span> input<span class="token punctuation">.</span>DigestAlgorithm<span class="token punctuation">)</span><span class="token punctuation">;</span>
 
        <span class="token keyword">if</span> <span class="token punctuation">(</span>result <span class="token operator">!=</span> <span class="token keyword">null</span><span class="token punctuation">)</span>
        <span class="token punctuation">{</span>
            <span class="token keyword">return</span> Convert<span class="token punctuation">.</span><span class="token function">ToBase64String</span><span class="token punctuation">(</span>result<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
        <span class="token keyword">else</span>
        <span class="token punctuation">{</span>
            <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">InvalidOperationException</span><span class="token punctuation">(</span><span class="token string">"Signing operation failed"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">static</span> <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token operator">?</span> <span class="token function">SignData</span><span class="token punctuation">(</span><span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> dataToSign<span class="token punctuation">,</span> <span class="token keyword">string</span><span class="token operator">?</span> digestAlgorithm<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        <span class="token keyword">string</span> certificateFilePassword <span class="token operator">=</span> <span class="token string">"johndoe"</span><span class="token punctuation">;</span>
        <span class="token keyword">string</span> certificateFilePath <span class="token operator">=</span> <span class="token string">"Resources/JohnDoe.pfx"</span><span class="token punctuation">;</span>
 
        <span class="token keyword">using</span> <span class="token punctuation">(</span>Stream stream <span class="token operator">=</span> File<span class="token punctuation">.</span><span class="token function">OpenRead</span><span class="token punctuation">(</span>certificateFilePath<span class="token punctuation">)</span><span class="token punctuation">)</span>
        <span class="token punctuation">{</span>
            <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> certRawData <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">byte</span><span class="token punctuation">[</span>stream<span class="token punctuation">.</span>Length<span class="token punctuation">]</span><span class="token punctuation">;</span>
            stream<span class="token punctuation">.</span><span class="token function">ReadExactly</span><span class="token punctuation">(</span>certRawData<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token keyword">int</span><span class="token punctuation">)</span>stream<span class="token punctuation">.</span>Length<span class="token punctuation">)</span><span class="token punctuation">;</span>
 
            <span class="token keyword">using</span> <span class="token punctuation">(</span>X509Certificate2 fullCert <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">X509Certificate2</span><span class="token punctuation">(</span>certRawData<span class="token punctuation">,</span> certificateFilePassword<span class="token punctuation">)</span><span class="token punctuation">)</span>
            <span class="token punctuation">{</span>
                <span class="token keyword">using</span> <span class="token punctuation">(</span>RSA<span class="token operator">?</span> rsa <span class="token operator">=</span> fullCert<span class="token punctuation">.</span><span class="token function">GetRSAPrivateKey</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
                <span class="token punctuation">{</span>
                    <span class="token keyword">if</span> <span class="token punctuation">(</span>rsa <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span>
                    <span class="token punctuation">{</span>
                        <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">InvalidOperationException</span><span class="token punctuation">(</span><span class="token string">"Certificate does not contain an RSA private key"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                    <span class="token punctuation">}</span>
 
                    <span class="token comment">// Map the digest algorithm string to HashAlgorithmName</span>
                    HashAlgorithmName algorithmName <span class="token operator">=</span> HashAlgorithmName<span class="token punctuation">.</span>SHA256<span class="token punctuation">;</span>
                    algorithmName <span class="token operator">=</span> digestAlgorithm <span class="token keyword">switch</span>
                    <span class="token punctuation">{</span>
                        <span class="token string">"Sha384"</span> <span class="token operator">=</span><span class="token operator">&gt;</span> HashAlgorithmName<span class="token punctuation">.</span>SHA384<span class="token punctuation">,</span>
                        <span class="token string">"Sha512"</span> <span class="token operator">=</span><span class="token operator">&gt;</span> HashAlgorithmName<span class="token punctuation">.</span>SHA512<span class="token punctuation">,</span>
                        _ <span class="token operator">=</span><span class="token operator">&gt;</span> HashAlgorithmName<span class="token punctuation">.</span>SHA256<span class="token punctuation">,</span>
                    <span class="token punctuation">}</span><span class="token punctuation">;</span>
 
                    <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token operator">?</span> bytes <span class="token operator">=</span> rsa<span class="token punctuation">.</span><span class="token function">SignData</span><span class="token punctuation">(</span>dataToSign<span class="token punctuation">,</span> algorithmName<span class="token punctuation">,</span> RSASignaturePadding<span class="token punctuation">.</span>Pkcs1<span class="token punctuation">)</span><span class="token punctuation">;</span>
                    <span class="token keyword">return</span> bytes<span class="token punctuation">;</span>
                <span class="token punctuation">}</span>
            <span class="token punctuation">}</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
 
    <span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Input</span>
    <span class="token punctuation">{</span>
        <span class="token keyword">public</span> <span class="token keyword">string</span> DataToSign <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token keyword">string</span><span class="token punctuation">.</span>Empty<span class="token punctuation">;</span>
 
        <span class="token keyword">public</span> <span class="token keyword">string</span><span class="token operator">?</span> DigestAlgorithm <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><ol start="4"><li>Modify the aws-lambda-tools-defaults.json file and specify the <code>function-name</code> for the AWS Lambda function (e.g., <code>ExternalSignPdfAWSFunction</code>):</li></ol><pre class=" language-json"><code class="prism  language-json"><span class="token punctuation">{</span>
  <span class="token string">"Information"</span><span class="token punctuation">:</span> <span class="token punctuation">[</span>
    <span class="token string">"This file provides default values for the deployment wizard inside Visual Studio and the AWS Lambda commands added to the .NET Core CLI."</span><span class="token punctuation">,</span>
    <span class="token string">"To learn more about the Lambda commands with the .NET Core CLI execute the following command at the command line in the project root directory."</span><span class="token punctuation">,</span>
    <span class="token string">"dotnet lambda help"</span><span class="token punctuation">,</span>
    <span class="token string">"All the command line options for the Lambda command can be specified in this file."</span>
  <span class="token punctuation">]</span><span class="token punctuation">,</span>
  <span class="token string">"profile"</span><span class="token punctuation">:</span> <span class="token string">"telerik-dpl"</span><span class="token punctuation">,</span>
  <span class="token string">"region"</span><span class="token punctuation">:</span> <span class="token string">"eu-north-1"</span><span class="token punctuation">,</span>
  <span class="token string">"configuration"</span><span class="token punctuation">:</span> <span class="token string">"Release"</span><span class="token punctuation">,</span>
  <span class="token string">"package-type"</span><span class="token punctuation">:</span> <span class="token string">"image"</span><span class="token punctuation">,</span>
  <span class="token string">"function-memory-size"</span><span class="token punctuation">:</span> <span class="token number">512</span><span class="token punctuation">,</span>
  <span class="token string">"function-timeout"</span><span class="token punctuation">:</span> <span class="token number">30</span><span class="token punctuation">,</span>
  <span class="token string">"image-command"</span><span class="token punctuation">:</span> <span class="token string">"MyAWSLambda::MyAWSLambda.Function::FunctionHandler"</span><span class="token punctuation">,</span>
  <span class="token string">"docker-host-build-output-dir"</span><span class="token punctuation">:</span> <span class="token string">"./bin/Release/lambda-publish"</span><span class="token punctuation">,</span>
  <span class="token string">"function-name"</span><span class="token punctuation">:</span> <span class="token string">"ExternalSignPdfAWSFunction"</span>
<span class="token punctuation">}</span>
</code></pre><ol start="5"><li><p>Create a Console App (e.g., MySigningApp.csproj) that will consume the AWS Lambda function.</p></li><li><p>Install the following NuGet packages:</p></li></ol><ul><li>AWSSDK.Lambda</li><li>Telerik.Documents.Fixed</li></ul><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2025/2025-12/lambda-packages.png?sfvrsn=b4ec15d_2" alt="MyAWSLambda - Packages" /></p><p>The <strong>Resources</strong> folder stores the unsigned PDF document together with the public .crt certificate.</p><ol start="7"><li>Modify the Program.cs file to demonstrate how to apply a digital signature to a PDF document using the Telerik <a target="_blank" href="https://docs.telerik.com/devtools/document-processing/libraries/radpdfprocessing/overview">PdfProcessing</a>library and an external AWS Lambda signer. The workflow includes importing a PDF, creating a <a target="_blank" href="https://docs.telerik.com/devtools/document-processing/libraries/radpdfprocessing/model/interactive-forms/form-fields/signaturefield">signature field</a> with a visual representation, configuring signature settings and exporting the signed document.</li></ol><p>Note: We will use the specified <code>function-name</code> in the previous step when creating the <code>LambdaFunctionSigner</code> object:</p><pre class=" language-csharp"><code class="prism  language-csharp"><span class="token keyword">using</span> System<span class="token punctuation">.</span>Diagnostics<span class="token punctuation">;</span>
<span class="token keyword">using</span> Telerik<span class="token punctuation">.</span>Documents<span class="token punctuation">.</span>Fixed<span class="token punctuation">.</span>Model<span class="token punctuation">.</span>DigitalSignatures<span class="token punctuation">;</span>
<span class="token keyword">using</span> Telerik<span class="token punctuation">.</span>Documents<span class="token punctuation">.</span>Primitives<span class="token punctuation">;</span>
<span class="token keyword">using</span> Telerik<span class="token punctuation">.</span>Windows<span class="token punctuation">.</span>Documents<span class="token punctuation">.</span>Fixed<span class="token punctuation">.</span>FormatProviders<span class="token punctuation">.</span>Pdf<span class="token punctuation">;</span>
<span class="token keyword">using</span> Telerik<span class="token punctuation">.</span>Windows<span class="token punctuation">.</span>Documents<span class="token punctuation">.</span>Fixed<span class="token punctuation">.</span>Model<span class="token punctuation">;</span>
<span class="token keyword">using</span> Telerik<span class="token punctuation">.</span>Windows<span class="token punctuation">.</span>Documents<span class="token punctuation">.</span>Fixed<span class="token punctuation">.</span>Model<span class="token punctuation">.</span>Annotations<span class="token punctuation">;</span>
<span class="token keyword">using</span> Telerik<span class="token punctuation">.</span>Windows<span class="token punctuation">.</span>Documents<span class="token punctuation">.</span>Fixed<span class="token punctuation">.</span>Model<span class="token punctuation">.</span>DigitalSignatures<span class="token punctuation">;</span>
<span class="token keyword">using</span> Telerik<span class="token punctuation">.</span>Windows<span class="token punctuation">.</span>Documents<span class="token punctuation">.</span>Fixed<span class="token punctuation">.</span>Model<span class="token punctuation">.</span>Editing<span class="token punctuation">;</span>
<span class="token keyword">using</span> Telerik<span class="token punctuation">.</span>Windows<span class="token punctuation">.</span>Documents<span class="token punctuation">.</span>Fixed<span class="token punctuation">.</span>Model<span class="token punctuation">.</span>InteractiveForms<span class="token punctuation">;</span>
<span class="token keyword">using</span> Telerik<span class="token punctuation">.</span>Windows<span class="token punctuation">.</span>Documents<span class="token punctuation">.</span>Fixed<span class="token punctuation">.</span>Model<span class="token punctuation">.</span>Objects<span class="token punctuation">;</span>
<span class="token keyword">using</span> Telerik<span class="token punctuation">.</span>Windows<span class="token punctuation">.</span>Documents<span class="token punctuation">.</span>Fixed<span class="token punctuation">.</span>Model<span class="token punctuation">.</span>Resources<span class="token punctuation">;</span>
 
<span class="token keyword">namespace</span> MySigningApp
<span class="token punctuation">{</span>
    <span class="token keyword">internal</span> <span class="token keyword">class</span> <span class="token class-name">Program</span>
    <span class="token punctuation">{</span>
        <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">Main</span><span class="token punctuation">(</span><span class="token keyword">string</span><span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span>
        <span class="token punctuation">{</span>
            PdfFormatProvider provider <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">PdfFormatProvider</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            RadFixedDocument document <span class="token operator">=</span> <span class="token function">ImportDocument</span><span class="token punctuation">(</span>provider<span class="token punctuation">)</span><span class="token punctuation">;</span>
 
            <span class="token keyword">string</span> signatureName <span class="token operator">=</span> <span class="token string">"SampleSignature"</span><span class="token punctuation">;</span>
 
            Form form <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Form</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            form<span class="token punctuation">.</span>FormSource <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">FormSource</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            form<span class="token punctuation">.</span>FormSource<span class="token punctuation">.</span>Size <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Size</span><span class="token punctuation">(</span><span class="token number">120</span><span class="token punctuation">,</span> <span class="token number">120</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 
            <span class="token comment">// We will use the editor to fill the Form XObject.  </span>
            FixedContentEditor formEditor <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">FixedContentEditor</span><span class="token punctuation">(</span>form<span class="token punctuation">.</span>FormSource<span class="token punctuation">)</span><span class="token punctuation">;</span>
            formEditor<span class="token punctuation">.</span><span class="token function">DrawCircle</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">Point</span><span class="token punctuation">(</span><span class="token number">50</span><span class="token punctuation">,</span> <span class="token number">50</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token number">20</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            formEditor<span class="token punctuation">.</span><span class="token function">DrawText</span><span class="token punctuation">(</span>signatureName<span class="token punctuation">)</span><span class="token punctuation">;</span>
 
            <span class="token comment">// The Signature object is added to a signature field, so we can add a visualization to it.  </span>
            SignatureField signatureField <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">SignatureField</span><span class="token punctuation">(</span>signatureName<span class="token punctuation">)</span><span class="token punctuation">;</span>
 
            <span class="token comment">// Create the external signer that will call AWS Lambda to perform the actual signing</span>
            ExternalSignerBase externalSigner <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">LambdaFunctionSigner</span><span class="token punctuation">(</span><span class="token string">"ExternalSignPdfAWSFunction"</span><span class="token punctuation">,</span> <span class="token string">"eu-north-1"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 
            <span class="token comment">// Configure the signature with digest algorithm and timestamp server</span>
            Signature signature <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Signature</span><span class="token punctuation">(</span>externalSigner<span class="token punctuation">)</span><span class="token punctuation">;</span>
            signature<span class="token punctuation">.</span>Settings<span class="token punctuation">.</span>DigestAlgorithm <span class="token operator">=</span> DigestAlgorithmType<span class="token punctuation">.</span>Sha512<span class="token punctuation">;</span>
            signature<span class="token punctuation">.</span>Settings<span class="token punctuation">.</span>TimeStampServer <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">TimeStampServer</span><span class="token punctuation">(</span><span class="token string">"http://timestamp.digicert.com"</span><span class="token punctuation">,</span> TimeSpan<span class="token punctuation">.</span><span class="token function">FromSeconds</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            signatureField<span class="token punctuation">.</span>Signature <span class="token operator">=</span> signature<span class="token punctuation">;</span>
 
            <span class="token comment">// The widget contains the Form XObject and defines the appearance of the signature field.  </span>
            SignatureWidget widget <span class="token operator">=</span> signatureField<span class="token punctuation">.</span>Widgets<span class="token punctuation">.</span><span class="token function">AddWidget</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            widget<span class="token punctuation">.</span>Rect <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Rect</span><span class="token punctuation">(</span><span class="token number">200</span><span class="token punctuation">,</span> <span class="token number">600</span><span class="token punctuation">,</span> <span class="token number">100</span><span class="token punctuation">,</span> <span class="token number">100</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            widget<span class="token punctuation">.</span>Border <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">AnnotationBorder</span><span class="token punctuation">(</span><span class="token number">100</span><span class="token punctuation">,</span> AnnotationBorderStyle<span class="token punctuation">.</span>Solid<span class="token punctuation">,</span> <span class="token keyword">null</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            widget<span class="token punctuation">.</span>Content<span class="token punctuation">.</span>NormalContentSource <span class="token operator">=</span> form<span class="token punctuation">.</span>FormSource<span class="token punctuation">;</span>
 
            <span class="token comment">// The Widget class inherits from Annotation. And, as any other annotation, must be added to the respective collection of the page.  </span>
            RadFixedPage page <span class="token operator">=</span> document<span class="token punctuation">.</span>Pages<span class="token punctuation">.</span><span class="token function">AddPage</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            page<span class="token punctuation">.</span>Annotations<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span>widget<span class="token punctuation">)</span><span class="token punctuation">;</span>
            document<span class="token punctuation">.</span>AcroForm<span class="token punctuation">.</span>FormFields<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span>signatureField<span class="token punctuation">)</span><span class="token punctuation">;</span>
 
            document<span class="token punctuation">.</span>AcroForm<span class="token punctuation">.</span>SignatureFlags <span class="token operator">=</span> SignatureFlags<span class="token punctuation">.</span>AppendOnly<span class="token punctuation">;</span>
 
            <span class="token function">ExportDocument</span><span class="token punctuation">(</span>provider<span class="token punctuation">,</span> document<span class="token punctuation">)</span><span class="token punctuation">;</span>
 
        <span class="token punctuation">}</span>
 
        <span class="token keyword">static</span> RadFixedDocument <span class="token function">ImportDocument</span><span class="token punctuation">(</span>PdfFormatProvider provider<span class="token punctuation">)</span>
        <span class="token punctuation">{</span>
            <span class="token keyword">using</span> <span class="token punctuation">(</span>FileStream stream <span class="token operator">=</span> File<span class="token punctuation">.</span><span class="token function">OpenRead</span><span class="token punctuation">(</span><span class="token string">"Resources/SampleDocument.pdf"</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
            <span class="token punctuation">{</span>
                <span class="token keyword">return</span> provider<span class="token punctuation">.</span><span class="token function">Import</span><span class="token punctuation">(</span>stream<span class="token punctuation">,</span> TimeSpan<span class="token punctuation">.</span><span class="token function">FromSeconds</span><span class="token punctuation">(</span><span class="token number">20</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">}</span>
        <span class="token punctuation">}</span>
 
        <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">ExportDocument</span><span class="token punctuation">(</span>PdfFormatProvider provider<span class="token punctuation">,</span> RadFixedDocument document<span class="token punctuation">)</span>
        <span class="token punctuation">{</span>
            <span class="token keyword">string</span> outputPath <span class="token operator">=</span> <span class="token string">"ExternallySignedDocument.pdf"</span><span class="token punctuation">;</span>
            File<span class="token punctuation">.</span><span class="token function">Delete</span><span class="token punctuation">(</span>outputPath<span class="token punctuation">)</span><span class="token punctuation">;</span>
 
            <span class="token keyword">using</span> <span class="token punctuation">(</span>FileStream stream <span class="token operator">=</span> File<span class="token punctuation">.</span><span class="token function">Create</span><span class="token punctuation">(</span>outputPath<span class="token punctuation">)</span><span class="token punctuation">)</span>
            <span class="token punctuation">{</span>
                provider<span class="token punctuation">.</span><span class="token function">Export</span><span class="token punctuation">(</span>document<span class="token punctuation">,</span> stream<span class="token punctuation">,</span> TimeSpan<span class="token punctuation">.</span><span class="token function">FromSeconds</span><span class="token punctuation">(</span><span class="token number">60</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">}</span>
 
            Process<span class="token punctuation">.</span><span class="token function">Start</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">ProcessStartInfo</span><span class="token punctuation">(</span>outputPath<span class="token punctuation">)</span> <span class="token punctuation">{</span> UseShellExecute <span class="token operator">=</span> <span class="token keyword">true</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><ol start="8"><li>Implement the External Signer.</li></ol><p>The <strong>LambdaFunctionSigner</strong> class is a custom implementation of an external signer that delegates digital signing operations to an AWS Lambda function. It inherits from <a target="_blank" href="https://docs.telerik.com/devtools/document-processing/libraries/radpdfprocessing/features/digital-signature/external-digital-signing#using-externalsignerbase"><strong>ExternalSignerBase</strong></a>and is designed for scenarios where the private key is securely stored in AWS Lambda, while the public certificate resides locally.</p><pre class=" language-csharp"><code class="prism  language-csharp"><span class="token keyword">using</span> Amazon<span class="token punctuation">.</span>Lambda<span class="token punctuation">;</span>
<span class="token keyword">using</span> Amazon<span class="token punctuation">.</span>Lambda<span class="token punctuation">.</span>Model<span class="token punctuation">;</span>
<span class="token keyword">using</span> Amazon<span class="token punctuation">.</span>Runtime<span class="token punctuation">;</span> 
<span class="token keyword">using</span> System<span class="token punctuation">.</span>Security<span class="token punctuation">.</span>Cryptography<span class="token punctuation">.</span>X509Certificates<span class="token punctuation">;</span>
<span class="token keyword">using</span> System<span class="token punctuation">.</span>Text<span class="token punctuation">;</span>
<span class="token keyword">using</span> System<span class="token punctuation">.</span>Text<span class="token punctuation">.</span>Json<span class="token punctuation">;</span>
<span class="token keyword">using</span> Telerik<span class="token punctuation">.</span>Documents<span class="token punctuation">.</span>Fixed<span class="token punctuation">.</span>Model<span class="token punctuation">.</span>DigitalSignatures<span class="token punctuation">;</span>
 
<span class="token keyword">namespace</span> MySigningApp
<span class="token punctuation">{</span>
    <span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">LambdaFunctionSigner</span> <span class="token punctuation">:</span> ExternalSignerBase
 
    <span class="token punctuation">{</span>
        <span class="token keyword">private</span> <span class="token keyword">readonly</span> <span class="token keyword">string</span> functionName<span class="token punctuation">;</span>
        <span class="token keyword">private</span> <span class="token keyword">readonly</span> AmazonLambdaClient lambdaClient<span class="token punctuation">;</span>
 
        <span class="token comment">/// &lt;summary&gt;</span>
        <span class="token comment">/// Creates a new instance of LambdaFunctionSigner.</span>
        <span class="token comment">/// &lt;/summary&gt;</span>
        <span class="token comment">/// &lt;param name="functionName"&gt;The AWS Lambda function name or ARN (e.g., "MyAWSLambda" or "arn:aws:lambda:region:account:function:name")&lt;/param&gt;</span>
        <span class="token comment">/// &lt;param name="region"&gt;The AWS region where the Lambda function is deployed (e.g., "us-east-1", "eu-north-1")&lt;/param&gt;</span>
        <span class="token keyword">public</span> <span class="token function">LambdaFunctionSigner</span><span class="token punctuation">(</span><span class="token keyword">string</span> functionName<span class="token punctuation">,</span> <span class="token keyword">string</span> region<span class="token punctuation">)</span>
        <span class="token punctuation">{</span>
            <span class="token keyword">this</span><span class="token punctuation">.</span>functionName <span class="token operator">=</span> functionName<span class="token punctuation">;</span>
            <span class="token keyword">var</span> credentials <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">BasicAWSCredentials</span><span class="token punctuation">(</span><span class="token string">"your-access-key"</span><span class="token punctuation">,</span> <span class="token string">"your-secret-key"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">this</span><span class="token punctuation">.</span>lambdaClient <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">AmazonLambdaClient</span><span class="token punctuation">(</span>credentials<span class="token punctuation">,</span> Amazon<span class="token punctuation">.</span>RegionEndpoint<span class="token punctuation">.</span><span class="token function">GetBySystemName</span><span class="token punctuation">(</span>region<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
 
        <span class="token comment">/// &lt;summary&gt;</span>
        <span class="token comment">/// Gets the certificate chain used for signing.</span>
        <span class="token comment">/// &lt;/summary&gt;</span>
        <span class="token comment">/// &lt;returns&gt;An array of X509Certificate2 objects representing the certificate chain.&lt;/returns&gt;</span>
        <span class="token comment">/// &lt;remarks&gt;</span>
        <span class="token comment">/// The public certificate is loaded from the Resources folder and should match</span>
        <span class="token comment">/// the private key certificate stored in the AWS Lambda function.</span>
        <span class="token comment">/// &lt;/remarks&gt;</span>
        <span class="token keyword">protected</span> <span class="token keyword">override</span> X509Certificate2<span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token function">GetCertificateChain</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
        <span class="token punctuation">{</span>
            <span class="token keyword">string</span> publicKey <span class="token operator">=</span> <span class="token string">"Resources/JohnDoe.crt"</span><span class="token punctuation">;</span>
            <span class="token keyword">return</span> <span class="token punctuation">[</span><span class="token keyword">new</span> <span class="token class-name">X509Certificate2</span><span class="token punctuation">(</span>publicKey<span class="token punctuation">)</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
 
        <span class="token comment">/// &lt;summary&gt;</span>
        <span class="token comment">/// Signs the provided data by invoking the AWS Lambda function.</span>
        <span class="token comment">/// &lt;/summary&gt;</span>
        <span class="token comment">/// &lt;param name="dataToSign"&gt;The byte array containing the data to be signed.&lt;/param&gt;</span>
        <span class="token comment">/// &lt;param name="settings"&gt;The signature settings containing digest algorithm and other configuration.&lt;/param&gt;</span>
        <span class="token comment">/// &lt;returns&gt;A byte array containing the digital signature.&lt;/returns&gt;</span>
        <span class="token comment">/// &lt;exception cref="InvalidOperationException"&gt;Thrown when the Lambda invocation fails or returns an error.&lt;/exception&gt;</span>
        <span class="token comment">/// &lt;remarks&gt;</span>
        <span class="token comment">/// This method:</span>
        <span class="token comment">/// 1. Serializes the data and settings to JSON</span>
        <span class="token comment">/// 2. Invokes the Lambda function synchronously</span>
        <span class="token comment">/// 3. Validates the response</span>
        <span class="token comment">/// 4. Returns the decoded signature bytes</span>
        <span class="token comment">/// &lt;/remarks&gt;</span>
        <span class="token keyword">protected</span> <span class="token keyword">override</span> <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token function">SignData</span><span class="token punctuation">(</span><span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> dataToSign<span class="token punctuation">,</span> SignatureSettings settings<span class="token punctuation">)</span>
        <span class="token punctuation">{</span>
            <span class="token keyword">var</span> requestData <span class="token operator">=</span> <span class="token keyword">new</span>
            <span class="token punctuation">{</span>
                DataToSign <span class="token operator">=</span> Convert<span class="token punctuation">.</span><span class="token function">ToBase64String</span><span class="token punctuation">(</span>dataToSign<span class="token punctuation">)</span><span class="token punctuation">,</span>
                DigestAlgorithm <span class="token operator">=</span> settings<span class="token punctuation">.</span>DigestAlgorithm<span class="token punctuation">.</span><span class="token function">ToString</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
            <span class="token punctuation">}</span><span class="token punctuation">;</span>
 
            <span class="token keyword">string</span> jsonRequest <span class="token operator">=</span> JsonSerializer<span class="token punctuation">.</span><span class="token function">Serialize</span><span class="token punctuation">(</span>requestData<span class="token punctuation">,</span> <span class="token keyword">new</span> <span class="token class-name">JsonSerializerOptions</span>
            <span class="token punctuation">{</span>
                WriteIndented <span class="token operator">=</span> <span class="token keyword">true</span>
            <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 
            <span class="token keyword">var</span> invokeRequest <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">InvokeRequest</span>
            <span class="token punctuation">{</span>
                FunctionName <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>functionName<span class="token punctuation">,</span>
                InvocationType <span class="token operator">=</span> InvocationType<span class="token punctuation">.</span>RequestResponse<span class="token punctuation">,</span> <span class="token comment">// synchronous</span>
                Payload <span class="token operator">=</span> jsonRequest
            <span class="token punctuation">}</span><span class="token punctuation">;</span>
 
            InvokeResponse invokeResponse <span class="token operator">=</span> lambdaClient<span class="token punctuation">.</span><span class="token function">InvokeAsync</span><span class="token punctuation">(</span>invokeRequest<span class="token punctuation">)</span><span class="token punctuation">.</span>Result<span class="token punctuation">;</span>
 
            <span class="token keyword">if</span> <span class="token punctuation">(</span>invokeResponse<span class="token punctuation">.</span>StatusCode <span class="token operator">!=</span> <span class="token number">200</span><span class="token punctuation">)</span>
            <span class="token punctuation">{</span>
                <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">InvalidOperationException</span><span class="token punctuation">(</span>$<span class="token string">"Lambda invocation failed with status code: {invokeResponse.StatusCode}"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">}</span>
 
            <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token keyword">string</span><span class="token punctuation">.</span><span class="token function">IsNullOrEmpty</span><span class="token punctuation">(</span>invokeResponse<span class="token punctuation">.</span>FunctionError<span class="token punctuation">)</span><span class="token punctuation">)</span>
            <span class="token punctuation">{</span>
                <span class="token keyword">string</span> errorMessage <span class="token operator">=</span> Encoding<span class="token punctuation">.</span>UTF8<span class="token punctuation">.</span><span class="token function">GetString</span><span class="token punctuation">(</span>invokeResponse<span class="token punctuation">.</span>Payload<span class="token punctuation">.</span><span class="token function">ToArray</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">InvalidOperationException</span><span class="token punctuation">(</span>$<span class="token string">"Lambda function error: {invokeResponse.FunctionError}. Details: {errorMessage}"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">}</span>
 
            <span class="token keyword">string</span> jsonResponse <span class="token operator">=</span> Encoding<span class="token punctuation">.</span>UTF8<span class="token punctuation">.</span><span class="token function">GetString</span><span class="token punctuation">(</span>invokeResponse<span class="token punctuation">.</span>Payload<span class="token punctuation">.</span><span class="token function">ToArray</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">string</span><span class="token operator">?</span> base64Signature <span class="token operator">=</span> JsonSerializer<span class="token punctuation">.</span><span class="token generic-method function">Deserialize<span class="token punctuation">&lt;</span><span class="token keyword">string</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span>jsonResponse<span class="token punctuation">)</span><span class="token punctuation">;</span>
 
            <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">string</span><span class="token punctuation">.</span><span class="token function">IsNullOrEmpty</span><span class="token punctuation">(</span>base64Signature<span class="token punctuation">)</span><span class="token punctuation">)</span>
            <span class="token punctuation">{</span>
                <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">InvalidOperationException</span><span class="token punctuation">(</span><span class="token string">"Invalid response from Lambda function"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">}</span>
 
            <span class="token keyword">return</span> Convert<span class="token punctuation">.</span><span class="token function">FromBase64String</span><span class="token punctuation">(</span>base64Signature<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><ol start="9"><li>Run the project.</li></ol><p>As a result, the unsigned PDF document is successfully signed:</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2025/2025-12/signed-pdf.png?sfvrsn=c5a33d9f_2" alt="PDF is signed and has certificate details" /></p><h2 id="wrapping-up">Wrapping Up</h2><p>Integrating Telerik Document Processing with Azure Functions and AWS Lambda demonstrates how serverless architectures can transform document workflows. By leveraging cloud scalability and pay-per-use models, organizations can efficiently handle tasks like PDF merging and secure digital signing without maintaining dedicated infrastructure. These approaches not only reduce operational overhead but also enhance security by isolating sensitive keys in the cloud.</p><p>As businesses continue to adopt remote and distributed solutions, similar patterns can be extended to other workflows such as document conversion, watermarking and batch processing, unlocking even greater flexibility and cost efficiency. The examples provided serve as a foundation for building robust, cloud-powered document services that scale seamlessly with demand.</p><p>Try out the <a target="_blank" href="https://www.telerik.com/document-processing-libraries">Telerik Document Processing Libraries</a>, which are included in the <a target="_blank" href="https://www.telerik.com/devcraft">Telerik DevCraft bundles</a> to pair perfectly with your favorite component libraries.</p><a target="_blank" href="https://www.telerik.com/try/devcraft-ultimate" class="Btn">Try Telerik DevCraft</a><img src="https://feeds.telerik.com/link/23072/17248733.gif" height="1" width="1"/>]]></content>
  </entry>
  <entry>
    <id>urn:uuid:72d23fd1-aa78-47ae-a659-de6b5b8467aa</id>
    <title type="text">Quick and Easy Conversion to PDF with Telerik Document Processing Library</title>
    <summary type="text">Learn how to quickly turn your documents into PDF using the power of Telerik Document Processing Library.</summary>
    <published>2025-01-22T16:13:01Z</published>
    <updated>2026-04-11T21:18:52Z</updated>
    <author>
      <name>Anna Velcheva </name>
    </author>
    <link rel="alternate" href="https://feeds.telerik.com/link/23072/16945224/quick-and-easy-conversion-to-pdf-with-telerik-document-processing-library"/>
    <content type="text"><![CDATA[<p><span class="featured">Learn how to quickly turn your documents into PDF using the power of Telerik Document Processing Library.</span></p><p>The PDF file format is a fixed format, which allows its creator full control on how the document content will be arranged and displayed. It is widely used and required in a variety of scenarios, which makes it an indispensable staple of past and present digital communication. Any application which deals with documents in any way cannot do without it.</p><p>Creating PDF files programmatically, however, is not so straightforward. The standard is intricate, and its specification is daunting in its size of about a thousand pages. Putting together a PDF file from scratch is realistically not a feasible task for many development teams.</p><p>In comes the Progress Telerik <a target="_blank" href="https://www.telerik.com/document-processing-libraries">Document Processing Libraries</a>&mdash;DPL for short. DPL is a set of .NET libraries which provide APIs for the creation of the most commonly used file formats and conversion between them. DPL is a great fit for web, desktop and cross-platform apps, both for modern .NET and .NET Framework. This blog post will show you how to use it to turn almost any document into a PDF.</p><h2 id="how-dpl-conversion-works">How DPL Conversion Works</h2><p>Here is the short and sweet version of the way DPL operates. Each file format has a class which corresponds to it. For example, for PDF this is RadFixedDocument, for DOCX this is RadFlowDocument, and for XLSX it is Workbook. One object of these classes corresponds to one file and can be either created from scratch or imported from a file.</p><p>Each format has one or more format provider classes which are responsible for its import and export. Converting a file to a PDF boils down to importing a file into an object and then exporting it again to a PDF file. Let&rsquo;s dive deeper into how this is done for each format.</p><h2 id="docx-to-pdf">DOCX to PDF</h2><p>Starting with the classics, DOCX is one of the most natural file formats to export to PDF. The DOCX format is imported into a <a target="_blank" href="https://docs.telerik.com/devtools/document-processing/libraries/radwordsprocessing/model/radflowdocument">RadFlowDocument</a> using the <a target="_blank" href="https://docs.telerik.com/devtools/document-processing/libraries/radwordsprocessing/formats-and-conversion/word-file-formats/docx/docxformatprovider">DocxFormatProvider</a>:</p><pre class=" language-csharp"><code class="prism  language-csharp">RadFlowDocument flowDocument<span class="token punctuation">;</span>

<span class="token keyword">using</span> <span class="token punctuation">(</span>Stream inputStream <span class="token operator">=</span> File<span class="token punctuation">.</span><span class="token function">OpenRead</span><span class="token punctuation">(</span><span class="token string">@"&hellip;\docxSample.docx"</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
  DocxFormatProvider docxProvider <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">DocxFormatProvider</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  flowDocument <span class="token operator">=</span> docxProvider<span class="token punctuation">.</span><span class="token function">Import</span><span class="token punctuation">(</span>inputStream<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><p>All the information, contents, styles, images are now in the flowDocument object. If you&rsquo;d like to make changes to the file, now is a good time to do so using the <a target="_blank" href="https://docs.telerik.com/devtools/document-processing/libraries/radwordsprocessing/overview">RadFlowDocument API</a>.</p><p>The next step is to export the object to PDF. This is done the same way as the import, but using the <a target="_blank" href="https://docs.telerik.com/devtools/document-processing/libraries/radwordsprocessing/formats-and-conversion/pdf/pdfformatprovider">dedicated PdfFormatProvider</a> for flow documents:</p><pre class=" language-csharp"><code class="prism  language-csharp"><span class="token keyword">using</span> <span class="token punctuation">(</span>Stream outputStream <span class="token operator">=</span> File<span class="token punctuation">.</span><span class="token function">Create</span><span class="token punctuation">(</span><span class="token string">@"&hellip;\docxToPdfSample.pdf"</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
  PdfFormatProvider pdfProvider <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">PdfFormatProvider</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  pdfProvider<span class="token punctuation">.</span><span class="token function">Export</span><span class="token punctuation">(</span>flowDocument<span class="token punctuation">,</span> outputStream<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><p><strong>DOCX</strong></p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2025/2025-01/document-docx.png?sfvrsn=9608d749_2" alt="A screenshot of a document with the docx ruler at top" /></p><p><strong>PDF</strong></p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2025/2025-01/document-pdf.png?sfvrsn=1ae66610_2" alt="A screenshot of a document in PDF form" /></p><p>If you would like to play around with what your document will look like as a PDF, check out our <a target="_blank" href="https://demos.telerik.com/document-processing/wordsprocessing/pdf_export">WordsProcessing export to PDF demo</a>.</p><h2 id="html-to-pdf">HTML to PDF</h2><p>HTML is another natural format to export to PDF. Our approach will be the same as DOCX. Import an HTML file into a RadFlowDocument object and export the object to a PDF file.</p><pre class=" language-csharp"><code class="prism  language-csharp">RadFlowDocument flowDocument<span class="token punctuation">;</span>

<span class="token keyword">using</span> <span class="token punctuation">(</span>Stream inputStream <span class="token operator">=</span> File<span class="token punctuation">.</span><span class="token function">OpenRead</span><span class="token punctuation">(</span><span class="token string">@"..\htmlSample.html"</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
  HtmlFormatProvider htmlProvider <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">HtmlFormatProvider</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  flowDocument <span class="token operator">=</span> htmlProvider<span class="token punctuation">.</span><span class="token function">Import</span><span class="token punctuation">(</span>inputStream<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">using</span> <span class="token punctuation">(</span>Stream outputStream <span class="token operator">=</span> File<span class="token punctuation">.</span><span class="token function">Create</span><span class="token punctuation">(</span><span class="token string">@"..\htmlToPdfSample.pdf"</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
  PdfFormatProvider pdfProvider <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">PdfFormatProvider</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  pdfProvider<span class="token punctuation">.</span><span class="token function">Export</span><span class="token punctuation">(</span>flowDocument<span class="token punctuation">,</span> outputStream<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><p>Once again, you can test this in the <a target="_blank" href="https://demos.telerik.com/document-processing/wordsprocessing/pdf_export">WordsProcessing export to PDF demo</a> and upload your own HTML file.</p><h2 id="xlsx-to-pdf">XLSX to PDF</h2><p>While DOCX and HTML fall into the domain of WordsProcessing, XLSX import and export are part of the SpreadProcessing library. The conversion mechanism, however, remains the same.</p><p>By now you probably already know the drill. Import the XLSX file into an object&mdash;in this case, <a target="_blank" href="https://docs.telerik.com/devtools/document-processing/libraries/radspreadprocessing/working-with-workbooks/working-with-workbooks-what-is-workbook">the Workbook</a>&mdash;and export it to PDF. SpreadProcessing has its own <a target="_blank" href="https://docs.telerik.com/devtools/document-processing/libraries/radspreadprocessing/formats-and-conversion/import-and-export-to-excel-file-formats/xlsx/xlsxformatprovider">PdfFormatProvider</a>, which we will use in this sample.</p><pre class=" language-csharp"><code class="prism  language-csharp">Workbook xlsxDocument<span class="token punctuation">;</span>

<span class="token keyword">using</span><span class="token punctuation">(</span>Stream inputStream <span class="token operator">=</span> File<span class="token punctuation">.</span><span class="token function">OpenRead</span><span class="token punctuation">(</span><span class="token string">@"..\xlsxSample.xlsx"</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
  XlsxFormatProvider xlsxFormatProvider <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">XlsxFormatProvider</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  xlsxDocument <span class="token operator">=</span> xlsxFormatProvider<span class="token punctuation">.</span><span class="token function">Import</span><span class="token punctuation">(</span>inputStream<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">using</span> <span class="token punctuation">(</span>Stream outStream <span class="token operator">=</span> File<span class="token punctuation">.</span><span class="token function">Create</span><span class="token punctuation">(</span><span class="token string">@"..\xlsxToPdfSample.pdf"</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
  PdfFormatProvider pdfFormatProvider <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">PdfFormatProvider</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  pdfFormatProvider<span class="token punctuation">.</span><span class="token function">Export</span><span class="token punctuation">(</span>xlsxDocument<span class="token punctuation">,</span> outStream<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><p><strong>XLSX</strong></p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2025/2025-01/spreadsheet-xlsx.png?sfvrsn=1bc8d8fe_2" alt="A screenshot of a spreadsheet of  a company&#39;s products, prices, etc in editable format" /></p><p><strong>PDF</strong></p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2025/2025-01/spreadsheet-pdf.png?sfvrsn=cdd5324f_2" alt="A screenshot of a spreadsheet of a company&#39;s products, prices, etc in PDF format. The " /></p><p>While DOCX and to some extent HTML come with an inherent page layout, XLSX does not split into pages that intuitively. SpreadProcessing will do the job, just as Excel does when you want to print a document, but you might want to make some adjustments if the result is not split and laid out as you expect.</p><p>This is what the <a target="_blank" href="https://docs.telerik.com/devtools/document-processing/libraries/radspreadprocessing/features/worksheetpagesetup">WorksheetPrintOptions</a> are for. They allow you to set print areas, fit the content horizontally or vertically, set the orientation of the page and much more. Let&rsquo;s make some changes to make our document fit better:</p><pre class=" language-csharp"><code class="prism  language-csharp"><span class="token keyword">using</span><span class="token punctuation">(</span>Stream inputStream <span class="token operator">=</span> File<span class="token punctuation">.</span><span class="token function">OpenRead</span><span class="token punctuation">(</span><span class="token string">@"..\xlsxSample.xlsx"</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">[</span>&hellip;<span class="token punctuation">]</span>

Worksheet worksheet <span class="token operator">=</span> xlsxDocument<span class="token punctuation">.</span>ActiveWorksheet<span class="token punctuation">;</span>
worksheet<span class="token punctuation">.</span>WorksheetPageSetup<span class="token punctuation">.</span>FitToPages <span class="token operator">=</span> <span class="token keyword">true</span><span class="token punctuation">;</span>
worksheet<span class="token punctuation">.</span>WorksheetPageSetup<span class="token punctuation">.</span>FitToPagesWide <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>
worksheet<span class="token punctuation">.</span>WorksheetPageSetup<span class="token punctuation">.</span>PageOrientation <span class="token operator">=</span> PageOrientation<span class="token punctuation">.</span>Landscape<span class="token punctuation">;</span>

<span class="token keyword">using</span> <span class="token punctuation">(</span>Stream outStream <span class="token operator">=</span> File<span class="token punctuation">.</span><span class="token function">Create</span><span class="token punctuation">(</span><span class="token string">@"..\xlsxToPdfSample.pdf"</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">[</span>&hellip;<span class="token punctuation">]</span>
</code></pre><p><strong>PDF</strong><br /><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2025/2025-01/adjusted-spreadsheet-pdf.png?sfvrsn=6cdcff3_2" alt="A screenshot of a spreadsheet of a company&#39;s products, prices, etc in PDF format—this time formatted to the correct width" /></p><h2 id="conclusion">Conclusion</h2><p>As you can see, with Telerik Document Processing Library, converting files to PDF is indeed quick and easy! Interested? Check out the DPL page, where you will find additional information, demos and documentation:</p><p><a target="_blank" href="https://www.telerik.com/document-processing-libraries">Document Processing Libraries</a></p><p>DPL is part of the following Telerik products:</p><ul><li><a target="_blank" href="https://www.telerik.com/blazor-ui">Telerik UI for Blazor</a></li><li><a target="_blank" href="https://www.telerik.com/aspnet-core-ui">Telerik UI for ASP.NET Core</a></li><li><a target="_blank" href="https://www.telerik.com/aspnet-mvc">Telerik UI for ASP.NET MVC</a></li><li><a target="_blank" href="https://www.telerik.com/products/aspnet-ajax.aspx">Telerik UI for ASP.NET AJAX</a></li><li><a target="_blank" href="https://www.telerik.com/maui-ui">Telerik UI for .NET MAUI</a></li><li><a target="_blank" href="https://www.telerik.com/products/winforms.aspx">Telerik UI for WinForms</a></li><li><a target="_blank" href="https://www.telerik.com/products/wpf/overview.aspx">Telerik UI for WPF</a></li><li>And the&nbsp;<a target="_blank" href="https://www.telerik.com/devcraft">Telerik DevCraft</a>&nbsp;bundle, which includes all of the above&mdash;<a href="https://www.telerik.com/try/devcraft-ultimate" target="_blank">try it</a> yourself!</li></ul><img src="https://feeds.telerik.com/link/23072/16945224.gif" height="1" width="1"/>]]></content>
  </entry>
  <entry>
    <id>urn:uuid:f5ff3850-1d8f-434a-bc34-c5467c41298e</id>
    <title type="text">Integrating AI Analysis with Telerik PDF Viewer in ASP.NET Core</title>
    <summary type="text">Learn how to get started with Azure’s AI services with an AI-enabled summary from a PDF document with Telerik UI for ASP.NET Core and Document Processing Libraries.</summary>
    <published>2024-10-01T15:22:05Z</published>
    <updated>2026-04-11T21:18:52Z</updated>
    <author>
      <name>Peter Vogel </name>
    </author>
    <link rel="alternate" href="https://feeds.telerik.com/link/23072/16944629/integrating-ai-analysis-telerik-pdf-viewer-aspnet-core"/>
    <content type="text"><![CDATA[<p><span class="featured">Learn how to get started with Azure&rsquo;s AI services with an AI-enabled summary from a PDF document with Telerik UI for ASP.NET Core and Document Processing Libraries.</span></p><p>While Progress Telerik is busy creating its own line of smart components (which you can try out on a <a target="_blank" href="https://www.google.com/search?q=site%3Atelerik.com+%22smart+ai%22">bunch of platforms</a>), there&rsquo;s nothing stopping your from integrating AI into your applications right now. You can, for example, start using Azure&rsquo;s Language Services in any application you&rsquo;re currently building.</p><p>To make that point (and show you how to get started with Azure&rsquo;s AI services), I&rsquo;m going to show how to create an AI-enabled summary from a PDF document (I&rsquo;ve got a kid going back to school and, I bet, he could find this useful). And, if you don&rsquo;t care about how to make this work and just want to see how good a job Azure&rsquo;s tools do in generating summaries from technical articles, scroll to the section at the end of this post called &ldquo;<a href="https://www.telerik.com/#so-how-good-are-the-summaries">So: How Good are the Summaries?</a>&rdquo; You&rsquo;ll find some summaries of a variety of business and geeky articles, along with links to the original articles. You can make up your own mind about how good the tools are.</p><p>For this case study, I&rsquo;m going to implement a solution in ASP.NET Core that displays the summary on the page above the PDF document. But, quite frankly, except for the markup making up the UI, the code you see would be same on any platform (and, if you use one of PDF Viewers from Progress Telerik, even the UI code will be similar, no matter what platform you try this on).</p><h2 id="signing-up-to-language-services">Signing Up to Language Services</h2><p>If you want to implement this yourself, you&rsquo;ll need start by creating an Azure Language Service. If you&rsquo;ve already signed up with Azure, you can use your existing login credentials to get to the <a target="_blank" href="https://portal.azure.com/#view/Microsoft_Azure_ProjectOxford/CognitiveServicesHub/~/TextAnalytics">Language service overview page</a>.</p><p>Once on the Azure AI Services | Language Service page, click on the +Create link in the horizontal menu on the right to start the Wizard that will create your service.</p><p>The first page in the wizard lists the included features of a language service and some additional customization features that you can add. The base features include default Text Summarization processing, which is all I need for this case study, so I just clicked on the &ldquo;Continue to create your resource&rdquo; button at the bottom of the page.</p><p>The next page includes the typical information required to create any Azure resource: Subscription, resource group, etc. You will need, when picking a region, to pick one that supports the AI features you want to use&mdash;in this case, text analysis summarization. East U.S. is both close to me and, as near as I can tell, supports all the AI services, so I selected that region. You might want to select a <a target="_blank" href="https://learn.microsoft.com/en-us/azure/ai-services/language-service/concepts/regional-support">closer region</a>.</p><p>You&rsquo;ll also find two items that aren&rsquo;t part of the regular resource-creation process:</p><ul><li>A pricing tier. You have two choices here: A free (F0) tier and a standard tier (S). Both will work. The F0 tier will limit you to 5,000 requests in a week, while the S level will give you up to 1,000 requests every minute. Both are probably more than enough for a proof-of-concept test (I&rsquo;d be surprised if using the S level costs you even a dollar for a proof-of-concept project).</li><li>The option stating that you&rsquo;ve read the documents on the responsible use of AI that are linked to from the page.</li></ul><p>After filling out this page, I skipped the rest of the wizard by clicking the Review + Create button. If you want to control network access, set up a managed identity to assign permissions or assign tags, you may want to visit the other pages. Once on the final page of the wizard, I clicked the Create button and waited patiently for my resource to be created.</p><p>Once your service is created, on the Azure site, enter Language in the search box at the top of the Azure page and select Language from the resulting dropdown list to be taken back to Azure AI Services | Language service page. You should find your new service listed there&mdash;click on the service to open its Overview page.</p><p>Your code is, eventually, going to require two pieces of information about the service:</p><ul><li>Its URL</li><li>The secret key that will give your application access to the service</li></ul><p>Both of those are available from the Overview page&rsquo;s Manage keys link&mdash;clicking on the link will takes you to the service&rsquo;s &ldquo;Keys and endpoint&rdquo; page. On that page, copy the values for <code class="inline-code">Key 1</code> (the secret key) and <code class="inline-code">EndPoint</code> (the service&rsquo;s URL) and paste them somewhere safe.</p><p>Once you&rsquo;ve got those two values, you can close down your Azure page.</p><h2 id="create-an-asp.net-core-project">Create an ASP.NET Core Project</h2><p>Rather than wait for my resource to be created, I started creating the ASP.NET Core application that will let me load a PDF file and call my new service to summarize its content. I set up the project, <a target="_blank" href="https://docs.telerik.com/aspnet-core/getting-started/first-steps">as usual for a Telerik-enabled project</a>.</p><p>Not surprisingly, I decided to use the <a target="_blank" href="https://www.telerik.com/aspnet-core-ui/pdf-viewer">ASP.NET Core PDF Viewer</a> to display the PDF document I was summarizing. The language service only accepts text files, so I also decided to use the <a target="_blank" href="https://www.telerik.com/document-processing-libraries">Telerik Document Processing Library</a> (DPL) objects to convert my PDF file to text. To support all of that, my project requires just three NuGet packages:</p><ul><li>AI-processing: Azure.AI.TextAnalytics</li><li>Telerik PDF Viewer: Telerik.UI.for.ASPNet.Core</li><li>Processing documents: Telerik.Documents.Fixed and Telerik.Web.PDF</li></ul><p>To load and display a PDF in the kendo-pdfviewer, I added this markup to a Razor Page (I could use the same code in any View for MVC-style processing):</p><pre class=" language-markup"><code class="prism  language-markup">@page
@model IndexModel
@addTagHelper *, Kendo.Mvc

<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>kendo-pdfviewer</span> <span class="token attr-name">height</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>1200<span class="token punctuation">"</span></span>
                 <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>pdfviewer<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dpl-processing</span> <span class="token attr-name">load-on-demand</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>read</span> <span class="token attr-name">url</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>/Home/GetInitialPDF<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dpl-processing</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>toolbar</span> <span class="token attr-name">enabled</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>false<span class="token punctuation">"</span></span><span class="token punctuation">/&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>kendo-pdfviewer</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>~/kendo-ui-license.js<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span><span class="token script language-javascript"></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>
</code></pre><p>The kendo-pdfviewer&rsquo;s read element&rsquo;s <code class="inline-code">url</code> attribute has to point to a method that will retrieve the initial document to display. As the URL in my sample code implies, I implemented that by creating method called <code class="inline-code">GetInitialPDF</code> in my project&rsquo;s Home controller.</p><p>In this code from my <code class="inline-code">GetInitialPDF</code> method, I use .NET&rsquo;s File object to load a PDF document (named sample.pdf) from a subfolder called Documents in my project&rsquo;s wwwroot folder. I use the Telerik <code class="inline-code">FixedDocument</code> object to create an object that the kendo-pdfviewer can display.</p><p>That code looks like this:</p><pre class=" language-csharp"><code class="prism  language-csharp">    <span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">HomeController</span>
    <span class="token punctuation">{</span>
        <span class="token keyword">public</span> IActionResult <span class="token function">GetInitialPdf</span><span class="token punctuation">(</span><span class="token keyword">int</span><span class="token operator">?</span> pageNumber<span class="token punctuation">)</span>
        <span class="token punctuation">{</span>
            JsonResult jrt<span class="token punctuation">;</span>

            <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> pdfBytes <span class="token operator">=</span> File<span class="token punctuation">.</span><span class="token function">ReadAllBytes</span><span class="token punctuation">(</span>
<span class="token string">@"wwwroot\Documents\sample.pdf"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">var</span> pdfDoc <span class="token operator">=</span> FixedDocument<span class="token punctuation">.</span><span class="token function">Load</span><span class="token punctuation">(</span>pdfBytes<span class="token punctuation">,</span> <span class="token keyword">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">if</span> <span class="token punctuation">(</span>pageNumber <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span>
            <span class="token punctuation">{</span>
                jrt <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">JsonResult</span><span class="token punctuation">(</span>pdfDoc<span class="token punctuation">.</span><span class="token function">ToJson</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">}</span>
            <span class="token keyword">else</span>
            <span class="token punctuation">{</span>
                jrt <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">JsonResult</span><span class="token punctuation">(</span>pdfDoc<span class="token punctuation">.</span><span class="token function">GetPage</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token keyword">int</span><span class="token punctuation">)</span>pageNumber<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">}</span>
            <span class="token keyword">return</span> jrt<span class="token punctuation">;</span>
        <span class="token punctuation">}</span>        
    <span class="token punctuation">}</span> 
</code></pre><h2 id="writing-the-ai-code">Writing the AI Code</h2><p>To generate the summary that I&rsquo;ll display above the PDF file in my webpage, I created a separate class called <code class="inline-code">AIProcessing</code> with a method called <code class="inline-code">GetSummary</code>. I set up the <code class="inline-code">GetSummary</code> method to return my summary (a string) and to accept the relative file path to the document in my website (also a string). I&rsquo;m eventually going to call an async method inside this method, so I set up my <code class="inline-code">GetSummary</code> method with <code class="inline-code">async</code> modifier and wrapped my return value in a Task object:</p><pre class=" language-csharp"><code class="prism  language-csharp"><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">AIProcessing</span>
<span class="token punctuation">{</span>    
    Internal <span class="token keyword">async</span> Task<span class="token operator">&lt;</span><span class="token keyword">string</span><span class="token operator">&gt;</span> <span class="token function">GetSummary</span><span class="token punctuation">(</span><span class="token keyword">string</span> docPath<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
</code></pre><p>Within my <code class="inline-code">GetSummary</code> method, I create:</p><ul><li>PdfFormatProvider to convert my PDF document into a Telerik RadFixedDocument</li><li>TextFormatProvider to convert my RadFixedDocument into text</li></ul><p>With those two objects in place, I use a .NET File object to read my document into a Stream that I import into the PdfFormatProvider to create a format-neutral RadFixedDocument. I then feed the RadFixedDocument to the TextFormatProvider&rsquo;s <code class="inline-code">Export</code> method to create my text document:</p><pre class=" language-csharp"><code class="prism  language-csharp">PdfFormatProvider pdfProv <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">PdfFormatProvider</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
TextFormatProvider txtProvider <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">TextFormatProvider</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">using</span> <span class="token punctuation">(</span>Stream str <span class="token operator">=</span> File<span class="token punctuation">.</span><span class="token function">OpenRead</span><span class="token punctuation">(</span>docPath<span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
    RadFixedDocument radDoc <span class="token operator">=</span> pdfProv<span class="token punctuation">.</span><span class="token function">Import</span><span class="token punctuation">(</span>str<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">string</span> txtDoc <span class="token operator">=</span> txtProvider<span class="token punctuation">.</span><span class="token function">Export</span><span class="token punctuation">(</span>radDoc<span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre><p>Now I have a text document that I can feed to my Language Service. The next step is to connect to my Language Service. I do that by creating a <code class="inline-code">TextAnalysisClient</code> object, passing the URL and secret key I copied from my service&rsquo;s &ldquo;Keys and endpoint&rdquo; page (I&rsquo;ve omitted those values from this sample code):</p><pre class=" language-csharp"><code class="prism  language-csharp">TextAnalyticsClient tac <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">TextAnalyticsClient</span><span class="token punctuation">(</span>
    <span class="token keyword">new</span> <span class="token class-name">Uri</span><span class="token punctuation">(</span><span class="token string">"&lt;Endpoint&gt;"</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
    <span class="token keyword">new</span> <span class="token class-name">AzureKeyCredential</span><span class="token punctuation">(</span><span class="token string">"&lt;Key 1&gt;"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre><p>To actually pass my text document to the service, I need to add the document to a List of TextDocumentInput objects &hellip; which means I first have to create a TextDocumentInput that holds my text document.</p><p>A TextDocumentInput consists of a unique identifier for the document (unique within the collection, at any rate) and the text document itself. For the key, I decided to use the name of my PDF file (I used the .NET Path class to pull the file name out of the filepath passed to my method). Once I&rsquo;ve created that TextDocumentInput, I add it to my list.</p><p>Here&rsquo;s that code:</p><pre class=" language-csharp"><code class="prism  language-csharp"><span class="token keyword">string</span> key <span class="token operator">=</span> Path<span class="token punctuation">.</span><span class="token function">GetFileName</span><span class="token punctuation">(</span>docPath<span class="token punctuation">)</span><span class="token punctuation">;</span>
TextDocumentInput doc <span class="token operator">=</span> <span class="token keyword">new</span><span class="token punctuation">(</span>key<span class="token punctuation">,</span> txtDoc<span class="token punctuation">)</span><span class="token punctuation">;</span>
IList<span class="token operator">&lt;</span>TextDocumentInput<span class="token operator">&gt;</span> docs <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">List</span><span class="token operator">&lt;</span>TextDocumentInput<span class="token operator">&gt;</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
docs<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span>doc<span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre><p>The next step is to create my summary by calling the Language Service&rsquo;s <code class="inline-code">AbstractiveSummarize</code> method and then catch the resulting <code class="inline-code">AbstractiveSummarizeOperation</code> object.</p><p>I won&rsquo;t lie: The summary is buried pretty deeply in the <code class="inline-code">AbstractiveSummarizeOperation</code> object. Once you have the object, you first call its <code class="inline-code">GetValues</code> method which hands back the collection of results from the analysis. The summaries that I&rsquo;m interested in for this case study are in the first results collection returned by the <code class="inline-code">GetValues</code> method, so I use this code to retrieve that collection of results:</p><pre class=" language-csharp"><code class="prism  language-csharp">AbstractiveSummarizeOperation aso <span class="token operator">=</span> <span class="token keyword">await</span> tac<span class="token punctuation">.</span><span class="token function">AbstractiveSummarizeAsync</span><span class="token punctuation">(</span>
WaitUntil<span class="token punctuation">.</span>Completed<span class="token punctuation">,</span> docs<span class="token punctuation">)</span><span class="token punctuation">;</span>
AbstractiveSummarizeResultCollection results <span class="token operator">=</span> aso<span class="token punctuation">.</span><span class="token function">GetValues</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">First</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre><p>Now that I&rsquo;ve got the result collection I&rsquo;m interested in, I pull out the result for the document I&rsquo;m interested in, using the key I created when adding the document to the list of documents I processed (in my case, that key was the file name). I worry about things so, in the following code, I check to see if I found a result and, if I did, pull out the text of the first summary in the result. That summary is what I return from this method (and if I don&rsquo;t find anything, I return an empty string):</p><pre class=" language-csharp"><code class="prism  language-csharp">AbstractiveSummarizeResult docResult <span class="token operator">=</span> results<span class="token punctuation">.</span><span class="token function">FirstOrDefault</span><span class="token punctuation">(</span>r <span class="token operator">=</span><span class="token operator">&gt;</span> r<span class="token punctuation">.</span>Id <span class="token operator">==</span> key<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>docResult <span class="token operator">!=</span> <span class="token keyword">null</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
    <span class="token keyword">return</span> docResult<span class="token punctuation">.</span>Summaries<span class="token punctuation">.</span><span class="token function">First</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span>Text<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> <span class="token keyword">string</span><span class="token punctuation">.</span>Empty<span class="token punctuation">;</span>
</code></pre><h2 id="adding-the-summary-to-the-page">Adding the Summary to the Page</h2><p>The last step is to display that summary on my page just above my PDF document. I just need update my Razor Page&rsquo;s <code class="inline-code">GetAsync</code> method with the code to call my <code class="inline-code">GetSummary</code> method and then update a property in my Razor page with the text summary the method returns. If I were using MVC-style processing, I&rsquo;d put this code in a method in my Controller that a user could surf to and update a property on the Model I would pass to the View holding my PDF Viewer.</p><p>This code catches the string returned by my <code class="inline-code">GetSummary</code> method and stuffs it into a property called summary:</p><pre class=" language-csharp"><code class="prism  language-csharp">    <span class="token keyword">public</span> <span class="token keyword">string</span> summary <span class="token punctuation">{</span> <span class="token keyword">get</span><span class="token punctuation">;</span> <span class="token keyword">set</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
        
    <span class="token keyword">public</span> <span class="token keyword">async</span> Task <span class="token function">OnGetAsync</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        AIProcessing aiproc <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">AIProcessing</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        summary <span class="token operator">=</span> <span class="token keyword">await</span> aiproc<span class="token punctuation">.</span><span class="token function">GetSummary</span><span class="token punctuation">(</span><span class="token string">@"wwwroot\Documents\526M_Labs.pdf"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
</code></pre><p>I feel that I should make at least <em>some</em> attempt to provide a readable display of the summary and the document, so I used this markup in my View to display the summary property (in Model.summary), just above my PDFViewer, inside a nicely formatted box:</p><pre class=" language-markup"><code class="prism  language-markup">@page
@model IndexModel
@addTagHelper *, Kendo.Mvc

<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span><span class="token style-attr language-css"><span class="token attr-name"> <span class="token attr-name">style</span></span><span class="token punctuation">="</span><span class="token attr-value"><span class="token property">width</span><span class="token punctuation">:</span> <span class="token number">800</span>px</span><span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>label</span><span class="token punctuation">&gt;</span></span>Summary:<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>label</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span><span class="token style-attr language-css"><span class="token attr-name"> <span class="token attr-name">style</span></span><span class="token punctuation">="</span><span class="token attr-value"><span class="token property">margin</span><span class="token punctuation">:</span> <span class="token number">20</span>px<span class="token punctuation">;</span> <span class="token property">padding</span><span class="token punctuation">:</span> <span class="token number">5</span>px<span class="token punctuation">;</span> <span class="token property">border</span><span class="token punctuation">:</span><span class="token number">1</span>px solid black<span class="token punctuation">;</span></span><span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
        @Model.summary
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>br</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>label</span><span class="token punctuation">&gt;</span></span>Full Document:<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>label</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span><span class="token style-attr language-css"><span class="token attr-name"> <span class="token attr-name">style</span></span><span class="token punctuation">="</span><span class="token attr-value"><span class="token property">margin</span><span class="token punctuation">:</span> <span class="token number">20</span>px</span><span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>kendo-pdfviewer</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>pdfviewer<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
&hellip;..
       <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>kendo-pdfviewer</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span>
</code></pre><p>Of course, you won&rsquo;t want an application that displays exactly one document. To add the ability to dynamically switch between documents and generate summaries for each document, you should look at the <a target="_blank" href="https://docs.telerik.com/aspnet-core/html-helpers/pdf/pdfviewer/overview">PDF Viewer&rsquo;s documentation</a>.</p><p>But that&rsquo;s your problem. What I wanted to know was: Are the summaries any good?</p><h2 id="so-how-good-are-the-summaries">So: How Good Are the Summaries?</h2><p>To test the quality of the summaries generated, I decided to use some of my own <a target="_blank" href="https://www.telerik.com/blogs/author/peter-vogel">articles, as published on the Telerik.com site</a>. Among other issues, this plan would avoid any copyright infringement issues. In addition, you can review those documents and make your own decision on how good the summaries are (that you&rsquo;ll also be driving up my readership statistic when you do is just a happy accident).</p><p>For my first test, I took a subject near and dear to my heart that has general appeal but also has some technical content: The second of a series of posts I did on the <a target="_blank" href="https://www.telerik.com/blogs/implementing-5-key-principles-creating-effective-uis-part-2">fundamental principles of UX design</a> (there&rsquo;s nothing wrong with the first post, but I wanted something a little geekier than that introductory post). Here&rsquo;s the AI generated summary:</p><blockquote><p>The article provides a comprehensive guide on implementing effective user interfaces (UIs) by adhering to five key principles. It emphasizes the importance of being consistent with design, leveraging design patterns, supporting user scenarios, organizing UIs logically, and conducting thorough testing. The author introduces the concept of supporting a user&rsquo;s mental model, whether it&rsquo;s guiding them through a process or replacing it with a new one that offers greater value. The article further delves into the use of progress bars, menu structures, and navigation tools to enhance the user experience. It also discusses the significance of understanding user expectations and mental models in creating intuitive and efficient UIs.</p></blockquote><p>And, I have to admit: That&rsquo;s a pretty good summary of what I covered in the article. To put it another way&mdash;if I was forced to write a 100-word summary of that post, I don&rsquo;t know that I could do better.</p><p>For my second test, I went with a post with very little technical content and more of a business orientation: A post on <a target="_blank" href="https://www.telerik.com/blogs/enterprise-reporting-best-practices-standards-reports-matter">enterprise reporting standards and best practices</a>. Here&rsquo;s the summary for that post, which is also pretty good:</p><blockquote><p>Enterprise reporting has evolved with self-service reporting tools, enabling users to transform data into valuable information independently. However, this progression has introduced two levels of reports: those created for individual or team use, and enterprise reports intended for a broader audience, often across multiple departments. To manage these reports effectively, it&rsquo;s crucial to organize them in a way that&rsquo;s intuitive for users, much like curating art in a museum. Each report should have a clear description, outlining its target audience, the questions it answers, and the data aggregation level, which aids in assessing report quality and relevance. Additionally, establishing consistent data sources, a standardized report format, and a company-wide style sheet are vital steps in ensuring the accuracy, accessibility, and coherence of enterprise reports.</p></blockquote><p>I would have made a couple of changes in this summary:</p><ul><li>In the third sentence, I would replace &ldquo;To manage these reports&rdquo; with &ldquo;To manage those reports for the broader audience.&rdquo;</li><li>In the second to last sentence, I would replace the clause &ldquo;which aids in assessing report quality and relevance&rdquo; with a separate sentence&mdash;something like &ldquo;Those are also criteria that can be used in assessing&hellip;&rdquo; Other than that, though, I&rsquo;d be happy with this summary.</li></ul><p>And for my final test &hellip; how about this document you just read (minus this paragraph and the next)? It&rsquo;s nerdier than the previous two documents and self-referential so it doesn&rsquo;t get it quite right, does it:</p><blockquote><p>The source document provides a comprehensive guide on integrating AI analysis with Telerik&rsquo;s PDF viewer and document processing tools, as well as implementing AI-enabled summaries using Azure&rsquo;s Language Services. It details the process of creating an ASP.NET Core application that can display a PDF document and call upon an AI service to generate a summary, which is then displayed above the document. The document emphasizes the importance of understanding user expectations and mental models in designing intuitive and efficient user interfaces. Additionally, the document includes a case study where the author tests the quality of AI-generated summaries using their own articles and explores the principles of effective user experience design.</p></blockquote><p>Plainly, the processor got a little confused between the content of the article and the examples that I used to demonstrate what you should expect from the tool (it was all too &ldquo;meta,&rdquo; I guess). But fixing that would just mean deleting two things: the second to last sentence on UI design and the clause at the end of the last sentence. I&rsquo;d also like to include a sentence about how this article contains all the code you need to implement language processing in your own application. Altogether, maybe 30 seconds&rsquo; work. I could live with that.</p><p>But that&rsquo;s only my opinion and I&rsquo;m <em>not</em> here to tell you what to think: You can skim the articles and make up your own mind. And, if you decide that the summaries have value and, with whatever issues you have, the AI generated summaries are better than no summary at all &hellip; well, now you know to add them to your own apps.</p><p>But here&rsquo;s the important part: I used the S, paid tier to build this case study. Development, testing and running all of these samples cost me a total of six cents. I can live with that. I might even do some more.</p><blockquote>He did, indeed, do more. Read the next post: <a href="https://www.telerik.com/blogs/applying-ai-document-analysis-blazor" target="_blank">Applying AI Document Analysis with Blazor</a>.</blockquote><hr /><p>Try out <a target="_blank" href="https://www.telerik.com/aspnet-core-ui">Telerik UI for ASP.NET Core</a> yourself, free for 30 days.
</p><p><a href="https://www.telerik.com/try/aspnet-core-ui" target="_blank" class="Btn">Try Now</a></p><img src="https://feeds.telerik.com/link/23072/16944629.gif" height="1" width="1"/>]]></content>
  </entry>
  <entry>
    <id>urn:uuid:82103306-c88e-48fa-9f7b-0f1bbb4a8a36</id>
    <title type="text">Exporting a WinForms GridView’s Content to Different Formats</title>
    <summary type="text">The smooth integration between the Telerik UI for WinForms suite and the Document Processing Libraries brings a full set of file formats that are supported by RadGridView and its export functionality.</summary>
    <published>2023-09-19T18:45:00Z</published>
    <updated>2026-04-11T21:18:52Z</updated>
    <author>
      <name>Desislava Yordanova </name>
    </author>
    <link rel="alternate" href="https://feeds.telerik.com/link/23072/16355982/exporting-winforms-gridview-content-different-formats"/>
    <content type="text"><![CDATA[<p><span class="featured">Integrate Telerik UI for WinForms and Document Processing Libraries with a full set of file formats supported by RadGridView and its export functionality.</span></p><p>The smooth integration between the Progress <a target="_blank" href="https://www.telerik.com/products/winforms.aspx">Telerik UI for WinForms suite</a> and the <a target="_blank" href="https://www.telerik.com/document-processing-libraries">Document Processing Libraries</a> brings a full set of file formats that are supported by RadGridView
    and its <a target="_blank" href="https://docs.telerik.com/devtools/winforms/controls/gridview/exporting-data/overview">export functionality</a>.</p><p><a target="_blank" href="https://www.telerik.com/products/winforms/gridview.aspx">RadGridView</a> can be exported to XLSX (XLS*), CSV, PDF, TXT and HTML. Considering the number of records and how important the style settings are
    to the generated file, we can optimize the export time by running the export asynchronously. Let&rsquo;s get familiar with all the options you have when you generate a file with the data stored in the grid control.</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2023/2023-09/file-formats.png?sfvrsn=2da68d8c_3" alt="csv, xls, txt, pdf" /></p><h2 id="export-with-radspreadprocessing">Export with RadSpreadProcessing</h2><p><a target="_blank" href="https://docs.telerik.com/devtools/winforms/controls/gridview/exporting-data/spread-export#spread-export"><strong>GridViewSpreadExport</strong></a> utilizes our <a target="_blank" href="https://docs.telerik.com/devtools/document-processing/libraries/radspreadprocessing/overview">RadSpreadProcessing</a> library to export the content of RadGridView to XLSX (XLS*), CSV, PDF and TXT formats.</p><p><em>The spread export functionality requires the TelerikExport.dll assembly. To access the types in TelerikExport, you must include the assembly in your project and reference the Telerik.WinControls.Export namespace.</em></p><pre class=" language-csharp"><code class="prism  language-csharp">GridViewSpreadExport spreadExporter <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">GridViewSpreadExport</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>radGridView1<span class="token punctuation">)</span><span class="token punctuation">;</span>
SpreadExportRenderer exportRenderer <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">SpreadExportRenderer</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">string</span> fileName <span class="token operator">=</span> <span class="token string">@"..\..\exportedFile.xlsx"</span><span class="token punctuation">;</span>
spreadExporter<span class="token punctuation">.</span><span class="token function">RunExport</span><span class="token punctuation">(</span>fileName<span class="token punctuation">,</span> exportRenderer<span class="token punctuation">)</span><span class="token punctuation">;</span>
Process<span class="token punctuation">.</span><span class="token function">Start</span><span class="token punctuation">(</span>fileName<span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2023/2023-09/gridview-exports.png?sfvrsn=36743af2_3" alt="GridViewSpreadExport" /></p><p>*Image export is not available in the XLS format provider.</p><p>You will notice that the default settings for the export wouldn&rsquo;t bring the same look and feel to the exported file. If you need to achieve as close as possible the style available in the grid inside the exported file, like columns&rsquo; width
    or font, you can enable the <strong>ExportVisualSettings</strong> property or handle the <a target="_blank" href="https://docs.telerik.com/devtools/winforms/controls/gridview/exporting-data/spread-export#cellformatting">CellFormatting</a> event and apply all the style changes you need.</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2023/2023-09/gridview-exports-cell-formatting.png?sfvrsn=75c7b3d7_3" alt="cell check to preserve cell formatting in gridview export" /></p><p>More information about the public API that the GridViewSpreadExport offers is available in the <a target="_blank" href="https://docs.telerik.com/devtools/winforms/controls/gridview/exporting-data/spread-export#properties">Properties</a> and <a target="_blank" href="https://docs.telerik.com/devtools/winforms/controls/gridview/exporting-data/spread-export#events">Events</a> sections in the online documentation.</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2023/2023-09/info-icon.png?sfvrsn=dd10459f_3" style="margin-bottom:5px;float:left;margin-right:15px;" class="-align-left" alt="" />Each column in RadGridView has an <strong>ExcelExportType</strong> property that you can use to explicitly set the data type of the cells in the exported document.</p><p>To change the format of the exported data: Set the <strong>ExcelExportType</strong> property of the specific column to <em>Custom</em> and specify the <strong>ExcelExportFormatString</strong> property with the desired format. (<a target="_blank" href="https://docs.telerik.com/devtools/document-processing/libraries/radspreadprocessing/features/format-codes">Read more.</a>)</p><pre class=" language-csharp"><code class="prism  language-csharp"><span class="token keyword">this</span><span class="token punctuation">.</span>radGridView1<span class="token punctuation">.</span>Columns<span class="token punctuation">[</span><span class="token string">"ProductID"</span><span class="token punctuation">]</span><span class="token punctuation">.</span>ExcelExportType <span class="token operator">=</span> Telerik<span class="token punctuation">.</span>WinControls<span class="token punctuation">.</span>UI<span class="token punctuation">.</span>Export<span class="token punctuation">.</span>DisplayFormatType<span class="token punctuation">.</span>Custom<span class="token punctuation">;</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>radGridView1<span class="token punctuation">.</span>Columns<span class="token punctuation">[</span><span class="token string">"ProductID"</span><span class="token punctuation">]</span><span class="token punctuation">.</span>ExcelExportFormatString <span class="token operator">=</span> <span class="token string">"#.#"</span><span class="token punctuation">;</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>radGridView1<span class="token punctuation">.</span>Columns<span class="token punctuation">[</span><span class="token string">"Unitprice"</span><span class="token punctuation">]</span><span class="token punctuation">.</span>ExcelExportType <span class="token operator">=</span> Telerik<span class="token punctuation">.</span>WinControls<span class="token punctuation">.</span>UI<span class="token punctuation">.</span>Export<span class="token punctuation">.</span>DisplayFormatType<span class="token punctuation">.</span>Currency<span class="token punctuation">;</span>
</code></pre><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2023/2023-09/change-format-exported-string.png?sfvrsn=34fcd1d_3" alt="Product ID and UnitPrice columns have been emphasized with a red box. In the export, the period is removed from the prouct ID and the currency formatting is removed from unit price" /></p><p>The <strong>ExportFormat</strong> property defines the format the grid will be exported to. The available values are:</p><ul><li>XLSX</li><li>PDF</li><li>CSV</li><li>TXT</li></ul><p>The default value of the property is XLSX, hence, if not otherwise specified, the exporter will export to XLSX.</p><aside><hr /><div class="row"><div class="col-4 u-normal-full u-small-mb0"><h4 class="u-fs20 u-fw5 u-lh125 u-mb0">Telerik RadGridView for WinForms: A Deep Dive and User Experience Guide</h4></div><div class="col-8"><p class="u-fs16 u-mb0"><a href="https://www.telerik.com/blogs/telerik-radgridview-winforms-deep-dive-user-experience-guide" target="_blank">Get a closer look at the functionalities available from Telerik UI for WinForms GridView</a> and see why it stands out from the crowd.</p></div></div><hr class="u-mb3" /></aside><h2 id="export-with-radspreadstreamprocessing">Export with RadSpreadStreamProcessing</h2><p>When it comes to a scenario of exporting a grid with a lot of records, e.g., 100,000 rows, it may require some time to generate the export file with the GridViewSpreadExport.</p><p>After performing a quick test, it took around <strong>50 seconds</strong> to export <strong>100K</strong> records with the GridViewSpreadExport:</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2023/2023-09/gridviewspreadexport-speed.png?sfvrsn=1a530e2a_3" alt="51540 milliseconds" /></p><p>Here comes the <a target="_blank" href="https://docs.telerik.com/devtools/winforms/controls/gridview/exporting-data/spreadstream-export">GridViewSpreadStreamExport</a> that uses the <a target="_blank" href="https://docs.telerik.com/devtools/document-processing/libraries/radspreadstreamprocessing/overview">RadSpreadStreamProcessing</a> library which allows you to create big documents (without loading the entire document in the memory) and export them to the most common formats. Thus, you can optimize the export time and memory
    consumption.
</p><pre class=" language-csharp"><code class="prism  language-csharp">GridViewSpreadStreamExport spreadStreamExport <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">GridViewSpreadStreamExport</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>radGridView1<span class="token punctuation">)</span><span class="token punctuation">;</span>
spreadStreamExport<span class="token punctuation">.</span>ExportVisualSettings <span class="token operator">=</span> <span class="token keyword">true</span><span class="token punctuation">;</span>
<span class="token keyword">string</span> fileName <span class="token operator">=</span> <span class="token string">@"..\..\exportedFile.xlsx"</span><span class="token punctuation">;</span>
spreadStreamExport<span class="token punctuation">.</span><span class="token function">RunExport</span><span class="token punctuation">(</span>fileName<span class="token punctuation">,</span> <span class="token keyword">new</span> <span class="token class-name">SpreadStreamExportRenderer</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre><p>As a result, the same number of grid rows are exported much faster with the stream export in around <strong>20</strong> seconds:</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2023/2023-09/gridviewspreadstreamexport-speed.png?sfvrsn=27539877_3" alt="21761 milliseconds" /></p><p><a target="_blank" href="https://docs.telerik.com/devtools/winforms/controls/gridview/exporting-data/spreadstream-export#properties">A full list of the public API and fine-tuning for the exported file can be found here.</a></p><h2 id="export-with-radpdfprocessing">Export with RadPdfProcessing</h2><p>RadGridView&rsquo;s data can be exported natively to the PDF format by <a target="_blank" href="https://docs.telerik.com/devtools/winforms/controls/gridview/exporting-data/export-to-pdf#exporting-data-using-gridviewpdfexport-object">GridViewPdfExport</a>,
 which utilizes the powerful <a target="_blank" href="https://docs.telerik.com/devtools/document-processing/libraries/radpdfprocessing/overview">RadPdfProcessing</a> library.</p><p>The GridViewPdfExport functionality is also located in the TelerikExport.dll assembly. You need to include the following namespace in order to access the types contained in TelerikExport: Telerik.WinControls.Export.</p><pre class=" language-csharp"><code class="prism  language-csharp">Telerik<span class="token punctuation">.</span>WinControls<span class="token punctuation">.</span>Export<span class="token punctuation">.</span>GridViewPdfExport pdfExporter <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Telerik<span class="token punctuation">.</span>WinControls<span class="token punctuation">.</span>Export<span class="token punctuation">.</span>GridViewPdfExport</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>radGridView1<span class="token punctuation">)</span><span class="token punctuation">;</span>
pdfExporter<span class="token punctuation">.</span>FileExtension <span class="token operator">=</span> <span class="token string">"pdf"</span><span class="token punctuation">;</span>
pdfExporter<span class="token punctuation">.</span>HiddenColumnOption <span class="token operator">=</span> Telerik<span class="token punctuation">.</span>WinControls<span class="token punctuation">.</span>UI<span class="token punctuation">.</span>Export<span class="token punctuation">.</span>HiddenOption<span class="token punctuation">.</span>DoNotExport<span class="token punctuation">;</span> <span class="token punctuation">;</span>
pdfExporter<span class="token punctuation">.</span>ShowHeaderAndFooter <span class="token operator">=</span> <span class="token keyword">true</span><span class="token punctuation">;</span>

pdfExporter<span class="token punctuation">.</span>HeaderHeight <span class="token operator">=</span> <span class="token number">30</span><span class="token punctuation">;</span>
pdfExporter<span class="token punctuation">.</span>HeaderFont <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Font</span><span class="token punctuation">(</span><span class="token string">"Arial"</span><span class="token punctuation">,</span> <span class="token number">22</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
pdfExporter<span class="token punctuation">.</span>Logo <span class="token operator">=</span> System<span class="token punctuation">.</span>Drawing<span class="token punctuation">.</span>Image<span class="token punctuation">.</span><span class="token function">FromFile</span><span class="token punctuation">(</span><span class="token string">@"C:\MyLogo.png"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
pdfExporter<span class="token punctuation">.</span>LeftHeader <span class="token operator">=</span> <span class="token string">"[Logo]"</span><span class="token punctuation">;</span>
pdfExporter<span class="token punctuation">.</span>LogoAlignment <span class="token operator">=</span> ContentAlignment<span class="token punctuation">.</span>MiddleLeft<span class="token punctuation">;</span>
pdfExporter<span class="token punctuation">.</span>LogoLayout <span class="token operator">=</span> Telerik<span class="token punctuation">.</span>WinControls<span class="token punctuation">.</span>Export<span class="token punctuation">.</span>LogoLayout<span class="token punctuation">.</span>Fit<span class="token punctuation">;</span>

pdfExporter<span class="token punctuation">.</span>MiddleHeader <span class="token operator">=</span> <span class="token string">"Middle header"</span><span class="token punctuation">;</span>
pdfExporter<span class="token punctuation">.</span>RightHeader <span class="token operator">=</span> <span class="token string">"Right header"</span><span class="token punctuation">;</span>
pdfExporter<span class="token punctuation">.</span>ReverseHeaderOnEvenPages <span class="token operator">=</span> <span class="token keyword">true</span><span class="token punctuation">;</span>

pdfExporter<span class="token punctuation">.</span>FooterHeight <span class="token operator">=</span> <span class="token number">30</span><span class="token punctuation">;</span>
pdfExporter<span class="token punctuation">.</span>FooterFont <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Font</span><span class="token punctuation">(</span><span class="token string">"Arial"</span><span class="token punctuation">,</span> <span class="token number">22</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
pdfExporter<span class="token punctuation">.</span>LeftFooter <span class="token operator">=</span> <span class="token string">"Left footer"</span><span class="token punctuation">;</span>
pdfExporter<span class="token punctuation">.</span>MiddleFooter <span class="token operator">=</span> <span class="token string">"Middle footer"</span><span class="token punctuation">;</span>
pdfExporter<span class="token punctuation">.</span>RightFooter <span class="token operator">=</span> <span class="token string">"Right footer"</span><span class="token punctuation">;</span>
pdfExporter<span class="token punctuation">.</span>ReverseFooterOnEvenPages <span class="token operator">=</span> <span class="token keyword">true</span><span class="token punctuation">;</span>

pdfExporter<span class="token punctuation">.</span>FitToPageWidth <span class="token operator">=</span> <span class="token keyword">true</span><span class="token punctuation">;</span>
<span class="token keyword">string</span> fileName <span class="token operator">=</span> <span class="token string">@"..\..\exportedFile.pdf"</span><span class="token punctuation">;</span>
pdfExporter<span class="token punctuation">.</span><span class="token function">RunExport</span><span class="token punctuation">(</span>fileName<span class="token punctuation">,</span> <span class="token keyword">new</span> <span class="token class-name">Telerik<span class="token punctuation">.</span>WinControls<span class="token punctuation">.</span>Export<span class="token punctuation">.</span>PdfExportRenderer</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2023/2023-09/exported-file-pdf.png?sfvrsn=f20742d_3" alt="PDF file has logo, middle header and right header" /></p><p>Once you have the grid&rsquo;s content exported to one of the above-mentioned file formats, with the help of the <a target="_blank" href="https://docs.telerik.com/devtools/document-processing/introduction">Document Processing Libraries</a> it is possible to manage further the file and convert it to any other format supported by the DPL.</p><h2 id="export-to-html">Export to HTML</h2><p>If you need to export the grid&rsquo;s content in HTML format, it is suitable to use the <a target="_blank" href="https://docs.telerik.com/devtools/winforms/controls/gridview/exporting-data/html-export">ExportToHTML</a> class.
        It offers excellent export performance and creates an HTML formatted file, which can be opened in a browser or MS Word. However, the HTML export is pretty old and its API is very limited.</p><p>That is why we strive to utilize as much as possible the rich API of our <a target="_blank" href="https://docs.telerik.com/devtools/document-processing/libraries/radpdfprocessing/overview">Document Processing Libraries</a> for exporting the RadGridView. It includes a set of cross-platform libraries that let you import and export content between different formats and work with archive files.</p><h2 id="try-telerik-ui-for-winforms-today">Try It for Free</h2><p>Try out the GridView and 160 other controls from <a href="https://www.telerik.com/products/winforms.aspx" target="_blank">Telerik UI for WinForms</a> today with our
        free trial:</p><p><a target="_blank" href="https://www.telerik.com/try/ui-for-winforms" class="Btn">Try Telerik UI for WinForms</a></p><p>Better yet, try Telerik UI for WinForms <strong>and</strong> <a href="https://www.telerik.com/document-processing-libraries">Document Processing Libraries</a>&nbsp;(and
 a bunch of other good stuff) with <a href="https://www.telerik.com/devcraft" target="_blank">Telerik DevCraft</a>&mdash;the most comprehensive UI component suite
        you can get your hands on:</p><p><a href="https://www.telerik.com/try/devcraft-ultimate" target="_blank" class="Btn">Try Telerik DevCraft</a></p><img src="https://feeds.telerik.com/link/23072/16355982.gif" height="1" width="1"/>]]></content>
  </entry>
  <entry>
    <id>urn:uuid:94a007ab-f22c-4aa1-93cd-ad84eef7dc89</id>
    <title type="text">Telerik PDFViewer Now Available as Part of Telerik UI for .NET MAUI</title>
    <summary type="text">Open, view and navigate through PDF documents from any device—mobile or desktop—with Telerik PDFViewer for .NET MAUI. See how!</summary>
    <published>2023-08-31T14:22:06Z</published>
    <updated>2026-04-11T21:18:52Z</updated>
    <author>
      <name>Rossitza Fakalieva </name>
    </author>
    <link rel="alternate" href="https://feeds.telerik.com/link/23072/16324179/telerik-pdfviewer-available-telerik-ui-net-maui"/>
    <content type="text"><![CDATA[<p><span class="featured">Open, view and navigate through PDF documents from any device&mdash;mobile or desktop&mdash;with Telerik PDFViewer for .NET MAUI. See how!</span></p><p>Working with PDF documents is a common request for every business application, no matter whether it is mobile, desktop or web. The Progress <a target="_blank" href="https://www.telerik.com/maui-ui">Telerik suite for .NET MAUI</a> offers a <a target="_blank" href="https://www.telerik.com/maui-ui/pdfprocessing">PDF library</a> to edit and create documents programmatically. And now with <a target="_blank" href="https://www.telerik.com/blogs/r2-2023-telerik-desktop-mobile-release">R2 2023</a>, you can display any PDF document you need to no matter whether it includes <strong>Images</strong>, <strong>Shapes, Links, Lists</strong> or various other visual elements.</p><p><a target="_blank" href="https://www.telerik.com/maui-ui/pdf-viewer">The PDF Viewer for .NET MAUI</a> is supported in Windows, macOS, iOS and Android platforms and comes with:</p><ul><li><strong>Support for various document sources</strong> &ndash; You can load a PDF document from a stream, from a file added as an embedded resource, a file located on the device and so on.</li><li><strong>Support for complex PDF structure</strong> &ndash; Link annotations, lists, visuals, different fonts and more.</li><li><strong>Zooming, continuous scrolling and navigation capabilities</strong> &ndash; You can choose between different layout modes and configure the level of zooming factor to magnify the documents.</li><li><strong>API for advanced scenarios</strong> &ndash; Tinker with the settings for more specialized situations such as opening password-protected documents, opening invalid documents and more.</li><li><strong>Load On Demand</strong> &ndash; The PDF Viewer control implements read-on-demand loading, and each page of the document loads dynamically only when it is shown in the PDF Viewer. When that page isn&rsquo;t in the view area, it gets unloaded.
        The stream that holds the document stays open while the document is used in PDF Viewer.</li><li><strong>BusyIndicator, toolbar with predefined items and rich customization options</strong> &ndash; Take advantage of a pre-defined UI automatically wired with some of the commands provided by the control through built-in functionality.</li></ul><p>Enough talking, let&rsquo;s see it in action:</p><h2 id="set-up-the-component-in-the-.net-maui-app">Set up the Component in the .NET MAUI App</h2><p>As with any of the other UI components, setting up Telerik UI for .NET MAUI is simple and can be done in three steps:</p><ol><li><a target="_blank" href="https://docs.telerik.com/devtools/maui/get-started/windows/first-steps-msi#step-2-download-telerik-ui-for-net-maui">Download and install Telerik UI for .NET MAUI.</a></li><li>Call the <strong><code class="inline-code">UseTelerik()</code></strong> method inside the Maui Program.cs file of your .NET MAUI project. This is needed for all Telerik UI for .NET MAUI components as <code class="inline-code">UseTelerik()</code> registers
        all built-in or additionally created handlers to the Telerik components.</li><li>Define Telerik PDFViewer in XAML or C#.</li></ol><p><strong>XAML</strong></p><pre class=" language-xml"><code class="prism  language-xml">xmlns:telerik="http://schemas.telerik.com/2022/xaml/maui"
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerik:</span>RadPdfViewer</span> <span class="token attr-name"><span class="token namespace">x:</span>Name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>pdfViewer<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
</code></pre><p><strong>C#</strong></p><pre class=" language-csharp"><code class="prism  language-csharp"><span class="token keyword">using</span> Telerik<span class="token punctuation">.</span>Maui<span class="token punctuation">.</span>Controls
RadPDfViewer pdfViewer <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">RadPdfViewer</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre><p>Now, if you run the application, the control will be there. But a document still needs to be loaded, so let&rsquo;s continue with this.</p><h2 id="display-documents-from-various-sources">Display Documents from Various Sources</h2><p>Documents can be loaded from various document sources like:</p><ul><li>FileDocument</li><li>Uri</li><li>ByteArray</li><li>Stream</li><li>FixedDocument</li></ul><p>The magic happens with the Source property of the component type&mdash;<strong>DocumentSource</strong> accepts FileName, UriBytes, FixedDocument or direct stream.</p><blockquote><p><strong>Note:</strong> Detailed illustrations for all types of sources can be found in <a target="_blank" href="https://docs.telerik.com/devtools/maui/controls/pdfviewer/display-documents">Telerik documentation</a>.</p></blockquote><p>For this post, we will open a document stored as part of the .NET MAUI application. The best way to do that is to use the Stream function to load the document as shown below:</p><pre class=" language-csharp"><code class="prism  language-csharp">Func<span class="token operator">&lt;</span>CancellationToken<span class="token punctuation">,</span>  Task<span class="token operator">&lt;</span>Stream<span class="token operator">&gt;</span><span class="token operator">&gt;</span> streamFunc <span class="token operator">=</span> ct <span class="token operator">=</span><span class="token operator">&gt;</span>  Task<span class="token punctuation">.</span><span class="token function">Run</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span>  <span class="token operator">=</span><span class="token operator">&gt;</span>  
<span class="token punctuation">{</span>  
  Assembly assembly <span class="token operator">=</span>  <span class="token keyword">typeof</span><span class="token punctuation">(</span>MinMaxZoomLevel<span class="token punctuation">)</span><span class="token punctuation">.</span>Assembly<span class="token punctuation">;</span>  
  <span class="token keyword">string</span> fileName <span class="token operator">=</span> assembly<span class="token punctuation">.</span><span class="token function">GetManifestResourceNames</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">FirstOrDefault</span><span class="token punctuation">(</span>n <span class="token operator">=</span><span class="token operator">&gt;</span> n<span class="token punctuation">.</span><span class="token function">Contains</span><span class="token punctuation">(</span><span class="token string">"pdfdoc.pdf"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// here we are searching for the resource document  </span>
  Stream stream <span class="token operator">=</span> assembly<span class="token punctuation">.</span><span class="token function">GetManifestResourceStream</span><span class="token punctuation">(</span>fileName<span class="token punctuation">)</span><span class="token punctuation">;</span>  
  <span class="token keyword">return</span> stream<span class="token punctuation">;</span>  
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>  
<span class="token keyword">this</span><span class="token punctuation">.</span>pdfViewer<span class="token punctuation">.</span>Source  <span class="token operator">=</span> streamFunc<span class="token punctuation">;</span>
</code></pre><p>Another good option is to use the integration between the Telerik PDF Processing library and create a FixedDocument/RadFixedDocument and use it as a Source to the PDFViewer.</p><p><a target="_blank" href="https://www.telerik.com/maui-ui/pdfprocessing">Telerik PDF Processing Library API</a> is part of Telerik UI for .NET MAUI, and you already have a reference to it once you added Telerik PDFViewer to your
    app. Learn more about what other capabilities this gives you here: <a target="_blank" href="https://www.telerik.com/document-processing-libraries">Telerik Document Processing</a>.</p><p>By using this approach, you have more control over the loading process. For example, you can modify the document after importing it and before assigning it as a Source to the PDF Viewer control.</p><p>Then the code will look like this:</p><pre class=" language-csharp"><code class="prism  language-csharp">Telerik<span class="token punctuation">.</span>Windows<span class="token punctuation">.</span>Documents<span class="token punctuation">.</span>Fixed<span class="token punctuation">.</span>FormatProviders<span class="token punctuation">.</span>Pdf<span class="token punctuation">.</span>PdfFormatProvider provider <span class="token operator">=</span>  <span class="token keyword">new</span>  <span class="token class-name">Telerik<span class="token punctuation">.</span>Windows<span class="token punctuation">.</span>Documents<span class="token punctuation">.</span>Fixed<span class="token punctuation">.</span>FormatProviders<span class="token punctuation">.</span>Pdf<span class="token punctuation">.</span>PdfFormatProvider</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>  
  Assembly assembly <span class="token operator">=</span>  <span class="token keyword">typeof</span><span class="token punctuation">(</span>MinMaxZoomLevel<span class="token punctuation">)</span><span class="token punctuation">.</span>Assembly<span class="token punctuation">;</span>  
  <span class="token keyword">string</span> fileName <span class="token operator">=</span> assembly<span class="token punctuation">.</span><span class="token function">GetManifestResourceNames</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">FirstOrDefault</span><span class="token punctuation">(</span>n <span class="token operator">=</span><span class="token operator">&gt;</span> n<span class="token punctuation">.</span><span class="token function">Contains</span><span class="token punctuation">(</span><span class="token string">"pdf-processing.pdf"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>  
  <span class="token keyword">using</span> <span class="token punctuation">(</span>Stream stream <span class="token operator">=</span> assembly<span class="token punctuation">.</span><span class="token function">GetManifestResourceStream</span><span class="token punctuation">(</span>fileName<span class="token punctuation">)</span><span class="token punctuation">)</span>  
  <span class="token punctuation">{</span>  
    RadFixedDocument document <span class="token operator">=</span> provider<span class="token punctuation">.</span><span class="token function">Import</span><span class="token punctuation">(</span>stream<span class="token punctuation">)</span><span class="token punctuation">;</span>  
    <span class="token keyword">this</span><span class="token punctuation">.</span>pdfViewer<span class="token punctuation">.</span>Source  <span class="token operator">=</span> document<span class="token punctuation">;</span>  
  <span class="token punctuation">}</span>
</code></pre><p>No matter which approach you choose, the result will be a loaded document, a beautiful long PDF with a table of contents, different fonts, tables, shapes and images.</p><p>Let&rsquo;s continue to work with this document to see what else we can do. The full document and demo can be found in <a target="_blank" href="https://github.com/telerik/maui-samples/tree/main/Samples/SdkBrowser/Examples/PdfViewerControl/GettingStartedCategory/GettingStartedExample">Telerik GitHub repo &ndash; Getting Started</a>.</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2023/2023-08/pdf-pages.png?sfvrsn=16d0ba2e_3" alt="a PDF document scrolled between two pages" /></p><h2 id="configure-the-document">Configure the Document</h2><h3 id="first-let’s-configure-the-fonts">First, Let&rsquo;s Configure the Fonts</h3><p>When you load a PDF document in Telerik PDF Viewer it already comes embedded with 14 standard fonts:</p><ul><li><span style="font-family:'Helvetica',sans-serif;">Helvetica</span></li><li><strong><span style="font-family:'Helvetica',sans-serif;">Helvetica-Bold</span></strong></li><li><em><span style="font-family:'Helvetica',sans-serif;">Helvetica-Oblique</span></em></li><li><strong><em><span style="font-family:'Helvetica',sans-serif;">Helvetica-BoldOblique</span></em></strong></li><li><span style="font-family:'Courier New';">Courier</span></li><li><strong><span style="font-family:'Courier New';">Courier-Bold</span></strong></li><li><span style="font-family:'Courier New';"><em>Courier-Oblique</em></span></li><li><strong><em><span style="font-family:'Courier New';">Courier-BoldOblique</span></em></strong></li><li><span style="font-family:'Times New Roman',serif;">Times-Roman</span></li><li><strong><span style="font-family:'Times New Roman',serif;">Times-Bold</span></strong></li><li><em><span style="font-family:'Times New Roman',serif;">Times-Italic</span></em></li><li><strong><em><span style="font-family:'Times New Roman',serif;">Times-BoldItalic</span></em></strong></li><li><span style="font-family:'Symbol';">Symbol</span> (Symbol)</li><li><span style="font-family:'Zapf Dingbats';">ZapfDingbats</span></li></ul><p>However, you can embed all other fonts that you want to be displayed using the <strong>RegisterFont</strong> method that is part of <a target="_blank" href="https://www.telerik.com/maui-ui/pdfprocessing">Telerik PdfProcessing Library API</a> .</p><pre class=" language-csharp"><code class="prism  language-csharp">Telerik<span class="token punctuation">.</span>Windows<span class="token punctuation">.</span>Documents<span class="token punctuation">.</span>Fixed<span class="token punctuation">.</span>Model<span class="token punctuation">.</span>Fonts<span class="token punctuation">.</span>FontsRepository<span class="token punctuation">.</span><span class="token function">RegisterFont</span><span class="token punctuation">(</span>  
<span class="token keyword">new</span>  <span class="token class-name">FontFamily</span><span class="token punctuation">(</span><span class="token string">"Verdana"</span><span class="token punctuation">)</span><span class="token punctuation">,</span>  FontStyles<span class="token punctuation">.</span>Normal<span class="token punctuation">,</span>  FontWeights<span class="token punctuation">.</span>Normal<span class="token punctuation">,</span> fontData<span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre><blockquote><p><strong>Note:</strong> Make sure to update the build action of the .ttf file to embedded resource.</p></blockquote><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2023/2023-08/pdf-fonts.png?sfvrsn=a84eb138_3" alt="A PDF showing different font families and sizes" /></p><h3 id="choose-a-layout-one-page-at-a-time-or-by-scrolling-to-the-end">Choose a Layout: One Page at a Time or by Scrolling to the End</h3><p><a target="_blank" href="https://www.telerik.com/maui-ui/pdf-viewer">The Telerik UI for .NET MAUI PDF Viewer</a> supports two layout modes that you can set through its <strong>LayoutMode</strong> property.</p><p>The available options are:</p><ul><li><code class="inline-code">ContinuousScroll</code> (default) &ndash; Displays pages in a continuous vertical column.</li><li><code class="inline-code">SinglePage</code> &ndash; Displays one page at a time.</li></ul><p>We will stay with ContinuousScroll, but you can switch to SinglePage like this: <code class="inline-code">LayoutMode="SinglePage"</code></p><p>You can also give the same control to the end user by exposing a separate UI and bind the <strong>ToggleLayoutModeCommand</strong> to it or add a <strong>ToggleLayoutModeToolbarItem</strong> to the toolbar (<em>wait a sec for that, when we will talk more about the ToolBar</em> ).</p><h3 id="control-the-space-between-pages">Control the Space Between Pages</h3><p>Once you choose the layout, you can continue with setting the space between pages using the <strong>PageSpacing</strong> property.</p><p>For example, if you want to have 50px between pages the code will look like this:</p><pre class=" language-xml"><code class="prism  language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerik:</span>RadPdfViewer</span> <span class="token attr-name"><span class="token namespace">x:</span>Name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>pdfViewer<span class="token punctuation">"</span></span> <span class="token attr-name">PageSpacing</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>50<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
</code></pre><h3 id="zooming--scrolling">Zooming &amp; Scrolling</h3><p><strong>RadPdfViewer</strong> offers a smooth end-user navigation experience with zooming and scrolling and a rich API to control it programmatically.</p><p>You can control the zoom level with two properties: <strong>MaxZoomLevel</strong> and <strong>MinZoomLevel</strong>. The default value of both is 0.3.</p><p>There are also commands that you can expose outside the component to build your own navigation:</p><ul><li>ZoomInCommand</li><li>ZoomOutCommand</li><li>NavigateToNextPageCommand</li><li>NavigateToPreviousPageCommand</li><li>NavigateToPageCommand</li></ul><h3 id="link-annotations">Link Annotations</h3><p>The Telerik .NET MAUI PDF Viewer supports link annotations and allows the end user to tap any hyperlink that leads to an absolute URI, and the link will open in the browser.</p><p>In addition, if the PDF contains links that point to bookmarks in the same document, the viewport scrolls to the destination specified in the link so you can easily display scenarios as Table of Contents, Sections and others.</p><p>The behavior can also be customized by subscribing to the <strong>LinkAnnotationTapped</strong> event which fires when a link is tapped/clicked. For example:</p><pre class=" language-csharp"><code class="prism  language-csharp"><span class="token keyword">private</span> <span class="token keyword">void</span> <span class="token function">LinkTapped</span><span class="token punctuation">(</span><span class="token keyword">object</span> sender<span class="token punctuation">,</span>  Telerik<span class="token punctuation">.</span>Maui<span class="token punctuation">.</span>Controls<span class="token punctuation">.</span>PdfViewer<span class="token punctuation">.</span>Annotations<span class="token punctuation">.</span>LinkAnnotationTappedEventArgs e<span class="token punctuation">)</span>  
<span class="token punctuation">{</span>  
  <span class="token keyword">if</span>  <span class="token punctuation">(</span>e<span class="token punctuation">.</span>LinkAnnotation<span class="token punctuation">.</span>Action  <span class="token keyword">is</span>  UriAction uriAction<span class="token punctuation">)</span>  
  <span class="token punctuation">{</span>  
    e<span class="token punctuation">.</span>Handled  <span class="token operator">=</span>  <span class="token keyword">true</span><span class="token punctuation">;</span>  
    Application<span class="token punctuation">.</span>Current<span class="token punctuation">.</span>MainPage<span class="token punctuation">.</span><span class="token function">DisplayAlert</span><span class="token punctuation">(</span><span class="token string">"Confirm"</span><span class="token punctuation">,</span>  <span class="token string">"Are you sure you want to navigate"</span><span class="token punctuation">,</span>  <span class="token string">"Yes"</span><span class="token punctuation">,</span>  <span class="token string">"No"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">ContinueWith</span><span class="token punctuation">(</span>t <span class="token operator">=</span><span class="token operator">&gt;</span>  
    <span class="token punctuation">{</span>  
      <span class="token keyword">bool</span> shouldNavigateAway <span class="token operator">=</span> t<span class="token punctuation">.</span>Status  <span class="token operator">==</span>  TaskStatus<span class="token punctuation">.</span>RanToCompletion  <span class="token operator">?</span> t<span class="token punctuation">.</span>Result  <span class="token punctuation">:</span>  <span class="token keyword">false</span><span class="token punctuation">;</span>  
      <span class="token keyword">if</span>  <span class="token punctuation">(</span>shouldNavigateAway<span class="token punctuation">)</span>  
      <span class="token punctuation">{</span>  
        Dispatcher<span class="token punctuation">.</span><span class="token function">Dispatch</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span>  <span class="token operator">=</span><span class="token operator">&gt;</span>  
        <span class="token punctuation">{</span>  
          Launcher<span class="token punctuation">.</span><span class="token function">OpenAsync</span><span class="token punctuation">(</span>uriAction<span class="token punctuation">.</span>Uri<span class="token punctuation">)</span><span class="token punctuation">;</span>  
        <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>  
      <span class="token punctuation">}</span>  
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>  
  <span class="token punctuation">}</span>  
<span class="token punctuation">}</span>
</code></pre><h3 id="password-protection">Password Protection</h3><p>Security and privacy is an important topic in the era of information that we are living in, so sometimes we need to work with password-protected documents and be cautious about the access we provide.</p><p>Telerik PDFViewer provides a <strong>SourcePasswordNeeded</strong> event to subscribe to validate the access to documents like this:</p><pre class=" language-csharp"><code class="prism  language-csharp"><span class="token keyword">private</span>  <span class="token keyword">void</span> <span class="token function">pdfViewer_SourcePasswordNeeded</span><span class="token punctuation">(</span><span class="token keyword">object</span> sender<span class="token punctuation">,</span>  Telerik<span class="token punctuation">.</span>Windows<span class="token punctuation">.</span>Documents<span class="token punctuation">.</span>Fixed<span class="token punctuation">.</span>FormatProviders<span class="token punctuation">.</span>Pdf<span class="token punctuation">.</span>Import<span class="token punctuation">.</span>PasswordNeededEventArgs e<span class="token punctuation">)</span>  
<span class="token punctuation">{</span>  
e<span class="token punctuation">.</span>Password  <span class="token operator">=</span>  <span class="token string">"my_user_password_here"</span><span class="token punctuation">;</span>  
<span class="token punctuation">}</span>
</code></pre><h3 id="manipulate-the-document-onload">Manipulate the Document OnLoad</h3><p>Sometimes we need to control end-user behavior or change something in the document when a page is loaded. The <code class="inline-code">OnPageElementsLoaded</code> is here for that. When this event fires we can access the page content and modify it like
    this:
</p><pre class=" language-csharp"><code class="prism  language-csharp"><span class="token keyword">private</span>  <span class="token keyword">void</span>  <span class="token function">OnPageElementsLoaded</span><span class="token punctuation">(</span><span class="token keyword">object</span> sender<span class="token punctuation">,</span>  PageElementsLoadedEventArgs e<span class="token punctuation">)</span>  
<span class="token punctuation">{</span>  
  <span class="token keyword">foreach</span>  <span class="token punctuation">(</span><span class="token keyword">var</span> item <span class="token keyword">in</span> e<span class="token punctuation">.</span>Page<span class="token punctuation">.</span>Content<span class="token punctuation">)</span>  
  <span class="token punctuation">{</span>  
    <span class="token keyword">if</span>  <span class="token punctuation">(</span>item <span class="token keyword">is</span>  Telerik<span class="token punctuation">.</span>Windows<span class="token punctuation">.</span>Documents<span class="token punctuation">.</span>Fixed<span class="token punctuation">.</span>Model<span class="token punctuation">.</span>Graphics<span class="token punctuation">.</span>Path path<span class="token punctuation">)</span>  
    <span class="token punctuation">{</span>  
      <span class="token keyword">if</span>  <span class="token punctuation">(</span>path<span class="token punctuation">.</span>StrokeThickness  <span class="token operator">==</span>  <span class="token number">0</span><span class="token punctuation">)</span>  
      <span class="token punctuation">{</span>  
        path<span class="token punctuation">.</span>StrokeThickness  <span class="token operator">=</span>  <span class="token number">5</span><span class="token punctuation">;</span>  
      <span class="token punctuation">}</span>  
    <span class="token punctuation">}</span>  
  <span class="token punctuation">}</span>  
<span class="token punctuation">}</span>
</code></pre><h3 id="handle-exception-scenarios-with-style">Handle Exception Scenarios with Style</h3><p>In some cases, the PDFViewer will fail to load the desired PDF document. The reason can be an invalid stream/inaccessible URL or invalid data in the document itself.</p><p>To handle these cases, use the <strong>SourceException</strong> event of the PDF Viewer:</p><pre class=" language-csharp"><code class="prism  language-csharp"><span class="token keyword">private</span>  <span class="token keyword">void</span>  <span class="token function">PdfViewerSourceException</span><span class="token punctuation">(</span><span class="token keyword">object</span> sender<span class="token punctuation">,</span>  SourceExceptionEventArgs e<span class="token punctuation">)</span>  
<span class="token punctuation">{</span>  
  <span class="token keyword">var</span> error <span class="token operator">=</span> e<span class="token punctuation">.</span>Exception<span class="token punctuation">.</span>Message<span class="token punctuation">;</span>  
<span class="token punctuation">}</span>
</code></pre><p>The PdfViewer will display the error like this:</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2023/2023-08/pdf-error.png?sfvrsn=45b715dd_3" alt="An error occurred while loading the document" /></p><p>This message will be automatically localized as <strong>Localization</strong> is part of the PDFViewer&rsquo;s features. However, if you need to change the text you can do it using the key <strong>PdfViewer_SourceExceptionMessage</strong> and follow the
    steps <a target="_blank" href="https://docs.telerik.com/devtools/maui/globalization-localization">here</a>.</p><p>Or you can change the whole UI that appears by using the <strong>SourceExceptionTemplate</strong> like this:</p><pre class=" language-xml"><code class="prism  language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerik:</span>RadPdfViewer</span>  <span class="token attr-name"><span class="token namespace">x:</span>Name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>pdfViewer<span class="token punctuation">"</span></span>  <span class="token attr-name">SourceException</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>PdfViewerSourceException<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>  
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerik:</span>RadPdfViewer.SourceExceptionTemplate</span><span class="token punctuation">&gt;</span></span>  
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>DataTemplate</span><span class="token punctuation">&gt;</span></span>  
      <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Label</span>  <span class="token attr-name">Text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Oops, something went wrong  ! We miss you and will be back soon ...<span class="token punctuation">"</span></span>  
<span class="token attr-name">TextColor</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Purple<span class="token punctuation">"</span></span>  
<span class="token attr-name">HorizontalTextAlignment</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Center<span class="token punctuation">"</span></span>  
<span class="token attr-name">VerticalTextAlignment</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Center<span class="token punctuation">"</span></span>  
<span class="token attr-name">LineBreakMode</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>WordWrap<span class="token punctuation">"</span></span>  <span class="token punctuation">/&gt;</span></span>  
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>DataTemplate</span><span class="token punctuation">&gt;</span></span>  
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span><span class="token namespace">telerik:</span>RadPdfViewer.SourceExceptionTemplate</span><span class="token punctuation">&gt;</span></span>  
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span><span class="token namespace">telerik:</span>RadPdfViewer</span><span class="token punctuation">&gt;</span></span>
</code></pre><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2023/2023-08/custom-error-pdf.png?sfvrsn=db0ed649_3" alt="In purple text, Oops, something went wrong {sad face} ! We miss you and will be back soon..." /></p><h2 id="configure-the-component-busy-indicator-toolbar--more">Configure the Component: Busy Indicator, ToolBar &amp; More</h2><p>As you see, there are a lot of features to customize the look and behavior of the displayed document. Now, let&rsquo;s see what else is hidden in the developer toolbox that enables you to configure the UI of the PDFViewer:</p><h3 id="busy-indicator">Busy Indicator</h3><p>Although the Telerik PDF Viewer is optimized for performance, sometimes it is possible to load a document that needs time to render. For such cases, a busy indicator visualizes to offer a smooth user experience.</p><p>By default, it is:</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2023/2023-08/default-loading-indicator.png?sfvrsn=c55064e4_3" alt="loading indicator is dashed circle in gradients of blue" /></p><p>You can customize its appearance by the <strong>BusyIndicatorTemplate</strong> property:</p><pre class=" language-xml"><code class="prism  language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerik:</span>RadPdfViewer</span>  <span class="token attr-name"><span class="token namespace">x:</span>Name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>pdfViewer<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>  
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerik:</span>RadPdfViewer.BusyIndicatorTemplate</span><span class="token punctuation">&gt;</span></span>  
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>DataTemplate</span><span class="token punctuation">&gt;</span></span>  
      <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerik:</span>RadBusyIndicator</span>  <span class="token attr-name">AnimationType</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Animation10<span class="token punctuation">"</span></span>  
<span class="token attr-name">AnimationContentHeightRequest</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>100<span class="token punctuation">"</span></span>  
<span class="token attr-name">AnimationContentWidthRequest</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>100<span class="token punctuation">"</span></span>  
<span class="token attr-name">IsBusy</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>True<span class="token punctuation">"</span></span>  <span class="token punctuation">/&gt;</span></span>  
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>DataTemplate</span><span class="token punctuation">&gt;</span></span>  
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span><span class="token namespace">telerik:</span>RadPdfViewer.BusyIndicatorTemplate</span><span class="token punctuation">&gt;</span></span>  
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span><span class="token namespace">telerik:</span>RadPdfViewer</span><span class="token punctuation">&gt;</span></span>
</code></pre><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2023/2023-08/custom-loading-indicator.png?sfvrsn=5e26a1e4_3" alt="loading indicator now with green dots" /></p><h3 id="toolbar">Toolbar</h3><p>Telerik PDFViewer comes with the option to be displayed with or without the Toolbar, where all configurable options for visualizing the document and controlling the navigation are exposed to the end user. Let&rsquo;s see how to do that:</p><h4 id="add-the-toolbar">Add the Toolbar</h4><p>The important part here is that you need to create an instance of RadPDfViewerToolbar component outside the pdfview but use the toolbar&rsquo;s PdfViewer property to associate with the PDFViewer component.</p><pre class=" language-xml"><code class="prism  language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerik:</span>RadPdfViewerToolbar</span>  <span class="token attr-name">PdfViewer</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding Source={x:Reference pdfViewer}}<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>  
&hellip;
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span><span class="token namespace">telerik:</span>RadPdfViewerToolbar</span><span class="token punctuation">&gt;</span></span>
  
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerik:</span>RadPdfViewer</span>  <span class="token attr-name"><span class="token namespace">x:</span>Name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>pdfViewer<span class="token punctuation">"</span></span>  <span class="token attr-name">Grid.Row</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>1<span class="token punctuation">"</span></span>  
<span class="token attr-name">Document</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding Document, Mode=OneWayToSource}<span class="token punctuation">"</span></span>  <span class="token punctuation">/&gt;</span></span>
</code></pre><h3 id="add-toolbar-items">Add Toolbar Items</h3><p>Then you can define which features are good for your users to display. There are two ways to do that:</p><h4 id="use-the-predefined-toolbar-items">Use the Predefined Toolbar Items</h4><p>PDFViewer&rsquo;s toolbar offers predefined toolbar items that have assigned any of the Commands it offers:</p><p><strong>PDFViewer commands with PDFViewer toolbar items:</strong></p><ul><li>FitToWidthCommand: <code class="inline-code">&lt;telerik:PdfViewerFitToWidthToolbarItem /&gt;</code></li><li>ZoomInCommand: <code class="inline-code">&lt;telerik:PdfViewerZoomInToolbarItem /&gt;</code></li><li>ZoomInCommand:<code class="inline-code">&lt;telerik:PdfViewerZoomOutToolbarItem /&gt;</code></li><li>NavigateToPreviousPageCommand: <code class="inline-code">&lt;telerik:PdfViewerNavigateToPreviousPageToolbarItem /&gt;</code></li><li>NavigateToNextPageCommand: <code class="inline-code">&lt;telerik:PdfViewerNavigateToNextPageToolbarItem /&gt;</code></li></ul><pre class=" language-xml"><code class="prism  language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerik:</span>RadPdfViewerToolbar</span> <span class="token attr-name">**PdfViewer**</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding Source={x:Reference pdfViewer}}<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerik:</span>PdfViewerFitToWidthToolbarItem</span>  <span class="token punctuation">/&gt;</span></span>  
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerik:</span>PdfViewerZoomInToolbarItem</span>  <span class="token punctuation">/&gt;</span></span>  
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerik:</span>PdfViewerZoomOutToolbarItem</span>  <span class="token punctuation">/&gt;</span></span>  
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerik:</span>PdfViewerNavigateToPreviousPageToolbarItem</span>  <span class="token punctuation">/&gt;</span></span>  
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerik:</span>PdfViewerNavigateToNextPageToolbarItem</span>  <span class="token punctuation">/&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span><span class="token namespace">telerik:</span>RadPdfViewerToolbar</span><span class="token punctuation">&gt;</span></span>
</code></pre><h4 id="use-regular-toolbar-items">Use Regular Toolbar Items</h4><p>RadPdfViewer Toolbar is inherited from <a target="_blank" href="https://www.telerik.com/maui-ui/toolbar">RadToolbar</a> with one additional <strong>PdfViewer</strong> property used to associate the PDFViewer component. That is
    why you can add regular toolbar items to its items collection and mix PDF Viewer toolbar items with regular ones.</p><p>Let&rsquo;s add a regular toolbaritem and associate it with a custom command or one of PDF Viewer commands:</p><pre class=" language-xml"><code class="prism  language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerik:</span>ButtonToolbarItem</span>  <span class="token attr-name">Command</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{Binding DisplayFileSizeCommand}<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerik:</span>ButtonToolbarItem.ImageSource</span><span class="token punctuation">&gt;</span></span>  
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>FontImageSource</span>  <span class="token attr-name">Glyph</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{x:Static telerik:TelerikFont.IconFile}<span class="token punctuation">"</span></span>  
      <span class="token attr-name">FontFamily</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>{x:Static telerik:TelerikFont.Name}<span class="token punctuation">"</span></span>  
      <span class="token attr-name">Size</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>16<span class="token punctuation">"</span></span><span class="token punctuation">/&gt;</span></span>  
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span><span class="token namespace">telerik:</span>ButtonToolbarItem.ImageSource</span><span class="token punctuation">&gt;</span></span>  
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span><span class="token namespace">telerik:</span>ButtonToolbarItem</span><span class="token punctuation">&gt;</span></span>
</code></pre><p>The result so far, where the last item is a regular ButtonToolbarItem:</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2023/2023-08/toolbar-button-item.png?sfvrsn=49ca79ed_3" alt="icons in the toolbar" /></p><h3 id="style-the-toolbar-items">Style the Toolbar Items</h3><p>Now, let&rsquo;s style them a little bit differently. As the PDFViewerToolbar is based on the RadToolbar control, all toolbar items in the PDFViewer inherit from <strong>ButtonToolbarItem</strong>. All styling properties available for the ButtonToolbarItem
    are also applicable to the PDF toolbar items.</p><p>For example, to change the background of the items defined above we can define the following style:</p><pre class=" language-xml"><code class="prism  language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Style</span>  <span class="token attr-name">TargetType</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>telerik:ButtonToolbarItemView<span class="token punctuation">"</span></span>  <span class="token attr-name"><span class="token namespace">x:</span>Key</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>commonStyle<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span><span class="token style language-css">  
  &lt;Setter  Property=<span class="token string">"MinimumWidthRequest"</span>  Value=<span class="token string">"40"</span>/&gt;  
  &lt;Setter  Property=<span class="token string">"BackgroundColor"</span>  Value=<span class="token string">"#608660C5"</span>/&gt;  
</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>Style</span><span class="token punctuation">&gt;</span></span>
</code></pre><p>And set it to them like this:</p><pre class=" language-xml"><code class="prism  language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerik:</span>PdfViewerZoomInToolbarItem</span><span class="token style-attr language-css"><span class="token attr-name">  <span class="token attr-name">Style</span></span><span class="token punctuation">="</span><span class="token attr-value"><span class="token punctuation">{</span>StaticResource commonStyle<span class="token punctuation">}</span></span><span class="token punctuation">"</span></span><span class="token punctuation">/&gt;</span></span>
</code></pre><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2023/2023-08/styled-toolbar-icon-buttons.png?sfvrsn=32acaafb_3" alt="each icon now has a light purple background, styled more like buttons" /></p><p>To read more details about Telerik Toolbar for .NET MAUI and see what else it can offer, read the <a target="_blank" href="https://www.telerik.com/blogs/build-beautiful-configuration-ui-both-desktop-mobile-telerik-ui-net-maui-toolbar">blog about the Toolbar</a>.</p><h2 id="migrating-from-xamarin">Migrating from Xamarin</h2><p>Telerik PDFViewer for .NET MAUI shares the same API as Telerik PDFViewer for Xamarin, so no big changes here. Still there two things to have in mind:</p><ul><li>ToolbarItems now receive the Pdf prefix so as not to conflict with the brand new RadToolBar for .NET MAUI component.</li><li>Namespace of the control is changed from Telerik.XamarinForms.PdfViewer to Telerik.Maui.Controls.</li></ul><p>For more details, you can refer to the <a target="_blank" href="https://docs.telerik.com/devtools/maui/controls/pdfviewer/migrate-from-xamarin">Telerik Migration from Xamarin article</a>.</p><p>Some of the features that the Xamarin version has are still in development in the .NET MAUI component, such as Text Selection and Text Search. They are scheduled for the next version of Telerik UI for .NET coming this autumn.  So stay tuned!</p><h2 id="more-to-explore">More to Explore</h2><p>More examples illustrating the power of Telerik PDFViewer and the rest of the UI components for .NET MAUI can be found in <a target="_blank" href="https://docs.telerik.com/devtools/maui/demos-and-sample-apps/sdkbrowser-app">Telerik SDK</a> and <a target="_blank" href="https://docs.telerik.com/devtools/maui/demos-and-sample-apps/controls-showcase-app">Telerik Controls Samples</a>.</p><p>More details about the API can be found in <a target="_blank" href="https://docs.telerik.com/devtools/maui/controls/toolbar/overview">Telerik documentation</a>.</p><p>Details about working with PDF documents programmatically are described in <a target="_blank" href="https://www.telerik.com/document-processing-libraries">Document Processing Libraries - Telerik</a>.</p><h2 id="тry-it-now">Тry It Now</h2><p>Working with PDF documents is one of a thousand scenarios that <strong>Telerik UI for .NET MAUI</strong> can unlock for you. </p><p>Try it now and, if there is anything you need, do not hesitate to share your <a target="_blank" href="https://feedback.telerik.com/maui">feedback</a> or questions with the Telerik team.</p><p><a target="_blank" href="https://www.telerik.com/try/ui-for-maui" class="Btn">Try Telerik UI for .NET MAUI</a></p><img src="https://feeds.telerik.com/link/23072/16324179.gif" height="1" width="1"/>]]></content>
  </entry>
  <entry>
    <id>urn:uuid:a474bf17-feed-41f2-9377-6cb7fd922ccd</id>
    <title type="text">Viewing and Downloading PDF Files with the Telerik UI for ASP.NET Core PDFViewer</title>
    <summary type="text">Open, view, download and print PDF documents from your ASP.NET Core app with the Telerik PDFViewer. See how!</summary>
    <published>2023-07-07T07:55:03Z</published>
    <updated>2026-04-11T21:18:52Z</updated>
    <author>
      <name>Ivan Danchev </name>
    </author>
    <link rel="alternate" href="https://feeds.telerik.com/link/23072/16226674/viewing-downloading-pdf-files-telerik-ui-aspnet-core-pdfviewer"/>
    <content type="text"><![CDATA[<p><span class="featured">Open, view, download and print PDF documents from your ASP.NET Core app with the Telerik PDFViewer. See how!</span></p><p>The Portable Document Format (PDF) file type has become ubiquitous in business and enabling users to view, and download a PDF document is a common application requirement. The <a target="_blank" href="https://www.telerik.com/aspnet-core-ui/pdf-viewer">PDFViewer component</a> from Progress <a target="_blank" href="https://www.telerik.com/aspnet-core-ui">Telerik UI for ASP.NET Core</a> provides
    many capabilities out of the box&mdash;allowing you to open, view, download and print PDF documents. The component renders the content of a PDF document in the browser as canvas.</p><p>There are two alternative ways to process PDFs in the PDFViewer: with the help of <a target="_blank" href="https://mozilla.github.io/pdf.js/">PDF.js</a> or the <a target="_blank" href="https://docs.telerik.com/devtools/document-processing/introduction">Telerik Document Processing</a> libraries. We will look at the configuration needed for the component to work in both scenarios.</p><h2 id="using-pdf.js-processing">Using PDF.js Processing</h2><p>You can set up the PDFViewer to use the <a target="_blank" href="https://mozilla.github.io/pdf.js/">PDF.js</a> client-side library for processing and rendering a PDF file. PDF.js is a community-driven library for parsing and rendering
    PDFs supported by Mozilla.</p><ol><li>Load the <strong>pdf.js</strong> library in the application Layout, or in the view you will be using the PDFViewer in.</li></ol><pre class=" language-html"><code class="prism  language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span>  <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.2.2/pdf.js<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span><span class="token script language-javascript"></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>
</code></pre><ol start="2"><li>In the view (e.g., Index.cshtml), declare the PDFViewer and set up its <strong>PdfjsProcessing</strong> configuration:</li></ol><pre class=" language-csharp"><code class="prism  language-csharp">@<span class="token punctuation">(</span>Html<span class="token punctuation">.</span><span class="token function">Kendo</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">PDFViewer</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">Name</span><span class="token punctuation">(</span><span class="token string">"pdfviewer"</span><span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">PdfjsProcessing</span><span class="token punctuation">(</span>pdf <span class="token operator">=</span><span class="token operator">&gt;</span> pdf<span class="token punctuation">.</span><span class="token function">File</span><span class="token punctuation">(</span>Url<span class="token punctuation">.</span><span class="token function">Content</span><span class="token punctuation">(</span><span class="token string">"~/App_Data/sample.pdf"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">Height</span><span class="token punctuation">(</span><span class="token number">900</span><span class="token punctuation">)</span>
<span class="token punctuation">)</span>
</code></pre><p>We want a specific file to be displayed when the page loads, so we&rsquo;ve set the path to the <strong>sample.pdf</strong> file in the <strong>File</strong> option within the PdfjsProcessing configuration. In this example, the file is located in the
    <strong>App_Data</strong> sub-folder of the application&rsquo;s <strong>wwwroot</strong> folder.</p><p>The result will look like this:</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2023/2023-06/pdfviewer.png?sfvrsn=aad28cf5_3" alt="PDF viewer with options for paging, zooming, selection tools, search, save, download, and print" /></p><p>Apart from displaying a file initially, the PDFViewer allows you to open a different PDF file that exists in the file system through the &ldquo;Open&rdquo; button in the toolbar.</p><h2 id="using-telerik-document-processing">Using Telerik Document Processing</h2><p>The alternative to using PDF.js for processing the PDFs is using the <a target="_blank" href="https://docs.telerik.com/devtools/document-processing/introduction">Telerik Document Processing</a> libraries. These libraries process
    the PDF document on the server and pass the data to the PDFViewer for visualization on the client.</p><p>Follow the steps below to set up the PDFViewer with Telerik Document Processing:</p><ol><li>Declare the component:</li></ol><pre class=" language-csharp"><code class="prism  language-csharp">@<span class="token punctuation">(</span>Html<span class="token punctuation">.</span><span class="token function">Kendo</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">PDFViewer</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">Name</span><span class="token punctuation">(</span><span class="token string">"pdfviewer1"</span><span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">DplProcessing</span><span class="token punctuation">(</span>dpl <span class="token operator">=</span><span class="token operator">&gt;</span>
    <span class="token punctuation">{</span>
      dpl<span class="token punctuation">.</span><span class="token function">Read</span><span class="token punctuation">(</span>r <span class="token operator">=</span><span class="token operator">&gt;</span> r<span class="token punctuation">.</span><span class="token function">Url</span><span class="token punctuation">(</span>Url<span class="token punctuation">.</span><span class="token function">Action</span><span class="token punctuation">(</span><span class="token string">"GetInitialPdf"</span><span class="token punctuation">,</span> <span class="token string">"Home"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      dpl<span class="token punctuation">.</span><span class="token function">Upload</span><span class="token punctuation">(</span>upload <span class="token operator">=</span><span class="token operator">&gt;</span> upload<span class="token punctuation">.</span><span class="token function">Url</span><span class="token punctuation">(</span>Url<span class="token punctuation">.</span><span class="token function">Action</span><span class="token punctuation">(</span><span class="token string">"GetPdf"</span><span class="token punctuation">,</span> <span class="token string">"Home"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">SaveField</span><span class="token punctuation">(</span><span class="token string">"file"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">Height</span><span class="token punctuation">(</span><span class="token number">900</span><span class="token punctuation">)</span>
<span class="token punctuation">)</span>
</code></pre><p>We will display the <strong>sample.pdf</strong> file initially, which is why we need to set the <strong>Read</strong> option in the <strong>DplProcessing</strong> configuration. It points to the <strong>GetInitialPdf</strong> action in the <strong>Home</strong> controller.</p><p>The <strong>Upload</strong> option is for opening another file from the file system. The action responsible for that is called <strong>GetPdf</strong>. When the user opens a file, it is sent for processing to the GetPdf action and then the file data is
    passed back to the PDfViewer, which visualizes it.</p><ol start="2"><li>Declare the <code class="inline-code">GetInitialPdf</code> and <code class="inline-code">GetPdf</code> actions in the Home controller.</li></ol><pre class=" language-csharp"><code class="prism  language-csharp"><span class="token keyword">public</span> IActionResult <span class="token function">GetInitialPdf</span><span class="token punctuation">(</span><span class="token keyword">int</span><span class="token operator">?</span> pageNumber<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
  JsonResult jsonResult<span class="token punctuation">;</span>
  <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> file <span class="token operator">=</span> System<span class="token punctuation">.</span>IO<span class="token punctuation">.</span>File<span class="token punctuation">.</span><span class="token function">ReadAllBytes</span><span class="token punctuation">(</span><span class="token string">@"wwwroot\App_Data\sample.pdf"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  FixedDocument doc <span class="token operator">=</span> FixedDocument<span class="token punctuation">.</span><span class="token function">Load</span><span class="token punctuation">(</span>file<span class="token punctuation">,</span> <span class="token keyword">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token keyword">if</span> <span class="token punctuation">(</span>pageNumber <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span>
  <span class="token punctuation">{</span>
    jsonResult <span class="token operator">=</span> <span class="token function">Json</span><span class="token punctuation">(</span>doc<span class="token punctuation">.</span><span class="token function">ToJson</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  <span class="token keyword">else</span>
  <span class="token punctuation">{</span>
    jsonResult <span class="token operator">=</span> <span class="token function">Json</span><span class="token punctuation">(</span>doc<span class="token punctuation">.</span><span class="token function">GetPage</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token keyword">int</span><span class="token punctuation">)</span>pageNumber<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  <span class="token keyword">return</span> jsonResult<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token punctuation">[</span>HttpPost<span class="token punctuation">]</span>
<span class="token keyword">public</span> IActionResult <span class="token function">GetPdf</span><span class="token punctuation">(</span>IFormFile file<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
  <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> data<span class="token punctuation">;</span>
  <span class="token keyword">using</span> <span class="token punctuation">(</span>Stream inputStream <span class="token operator">=</span> file<span class="token punctuation">.</span><span class="token function">OpenReadStream</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
  <span class="token punctuation">{</span>
    MemoryStream memoryStream <span class="token operator">=</span> inputStream <span class="token keyword">as</span> MemoryStream<span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>memoryStream <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
      memoryStream <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">MemoryStream</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      inputStream<span class="token punctuation">.</span><span class="token function">CopyTo</span><span class="token punctuation">(</span>memoryStream<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    data <span class="token operator">=</span> memoryStream<span class="token punctuation">.</span><span class="token function">ToArray</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  FixedDocument dox <span class="token operator">=</span> FixedDocument<span class="token punctuation">.</span><span class="token function">Load</span><span class="token punctuation">(</span>data<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">return</span> <span class="token function">Json</span><span class="token punctuation">(</span>dox<span class="token punctuation">.</span><span class="token function">ToJson</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><ol start="3"><li>When you add the two actions, Visual Studio will prompt you for missing dependencies. The processing logic in the actions depends on the Telerik Document Processing assemblies, which come with the <strong>Telerik.Web.PDF</strong> NuGet package. To
        resolve the missing dependencies, install the <strong>Telerik.Web.PDF</strong> NuGet package from Visual Studio&rsquo;s NuGet Package Manager and add the following &ldquo;using&rdquo; statement to the controller:</li></ol><pre class=" language-csharp"><code class="prism  language-csharp"><span class="token keyword">using</span> Telerik<span class="token punctuation">.</span>Web<span class="token punctuation">.</span>PDF<span class="token punctuation">;</span>
</code></pre><h2 id="toolbar-configuration-and-customization">Toolbar Configuration and Customization</h2><h3 id="toolbar-items-collection">Toolbar Items Collection</h3><p>Once you&rsquo;ve chosen one of the available processing approaches, you can customize the PDFViewer&rsquo;s toolbar and hide the tools you don&rsquo;t need.</p><p>The PDFViewer displays a set of default tools in its toolbar. If your use case requires hiding some options, you can use the <strong>Toolbar</strong> configuration of the component and explicitly declare the tools that will be shown in the toolbar.</p><p>In the following exemplary toolbar configuration, the <strong>Toolbar.Items</strong> collection specifies the tools that will be shown.</p><p>Note that the <strong>&ldquo;open&rdquo;</strong> tool is not declared. As a result, the &ldquo;Open&rdquo; button will not appear in the toolbar and the user would only be able to view the PDF document you&rsquo;ve chosen to load in the PDFViewer. They
    would not be able to open another file.
</p><pre class=" language-csharp"><code class="prism  language-csharp">@<span class="token punctuation">(</span>Html<span class="token punctuation">.</span><span class="token function">Kendo</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">PDFViewer</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">Name</span><span class="token punctuation">(</span><span class="token string">"pdfviewer"</span><span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">PdfjsProcessing</span><span class="token punctuation">(</span>pdf <span class="token operator">=</span><span class="token operator">&gt;</span> pdf
    <span class="token punctuation">.</span><span class="token function">File</span><span class="token punctuation">(</span>Url<span class="token punctuation">.</span><span class="token function">Content</span><span class="token punctuation">(</span><span class="token string">"~/Content/pdf/sample.pdf"</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
  <span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">Toolbar</span><span class="token punctuation">(</span>toolbar <span class="token operator">=</span><span class="token operator">&gt;</span>
    toolbar<span class="token punctuation">.</span><span class="token function">Items</span><span class="token punctuation">(</span>items <span class="token operator">=</span><span class="token operator">&gt;</span>
    <span class="token punctuation">{</span>
      items<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Name</span><span class="token punctuation">(</span><span class="token string">"pager"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      items<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Name</span><span class="token punctuation">(</span><span class="token string">"spacer"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      items<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Name</span><span class="token punctuation">(</span><span class="token string">"zoom"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      items<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Name</span><span class="token punctuation">(</span><span class="token string">"zoomInOut"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      items<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Name</span><span class="token punctuation">(</span><span class="token string">"toggleSelection"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      items<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Name</span><span class="token punctuation">(</span><span class="token string">"spacer"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      items<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Name</span><span class="token punctuation">(</span><span class="token string">"search"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      items<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Name</span><span class="token punctuation">(</span><span class="token string">"download"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      items<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Name</span><span class="token punctuation">(</span><span class="token string">"print"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">Height</span><span class="token punctuation">(</span><span class="token number">900</span><span class="token punctuation">)</span>
<span class="token punctuation">)</span>
</code></pre><p>You will notice that the <strong>&ldquo;spacer&rdquo;</strong> tool is declared twice. Its purpose is to create an empty space between the tools. You can use it to group some of the tools or to isolate one tool from the rest.</p><p>You will get the following toolbar with the configuration posted above:</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2023/2023-06/pdf-toolbar.png?sfvrsn=d673715d_3" alt="options for paging, zooming, selection tools, search, save, download, and print" /></p><h3 id="toolbar-item-template">Toolbar Item Template</h3><p>You can go even further in the customization of the PDFViewer&rsquo;s toolbar and declare custom tools by using the <strong>Template</strong> option.</p><p>The example below shows a button added as a custom tool along with some of the default tools:</p><pre class=" language-csharp"><code class="prism  language-csharp"><span class="token punctuation">.</span><span class="token function">Toolbar</span><span class="token punctuation">(</span>toolbar <span class="token operator">=</span><span class="token operator">&gt;</span>
  toolbar<span class="token punctuation">.</span><span class="token function">Items</span><span class="token punctuation">(</span>items <span class="token operator">=</span><span class="token operator">&gt;</span>
  <span class="token punctuation">{</span>
    items<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Name</span><span class="token punctuation">(</span><span class="token string">"pager"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    items<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Name</span><span class="token punctuation">(</span><span class="token string">"spacer"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    items<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Name</span><span class="token punctuation">(</span><span class="token string">"Custom"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Template</span><span class="token punctuation">(</span><span class="token string">"&lt;button class='k-button k-button-solid k-button-md k-rounded-md k-button-solid-base k-icon-button'&gt;&lt;span class='k-button-icon k-icon k-i-cog'&gt;&lt;/span&gt;&lt;/button&gt;"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    items<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Name</span><span class="token punctuation">(</span><span class="token string">"search"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    items<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Name</span><span class="token punctuation">(</span><span class="token string">"download"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    items<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Name</span><span class="token punctuation">(</span><span class="token string">"print"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">)</span>
</code></pre><p>You can attach a &ldquo;click&rdquo; handler to the button and execute your custom logic in it.</p><p>Next, we will look at a different scenario that involves both customizing the PDFViewer&rsquo;s toolbar and using the API of the component.</p><h2 id="taking-advantage-of-the-api">Taking Advantage of the API</h2><p>You may have a requirement to disable the download of PDF files, until the user accepts a terms of use agreement. A message will ask the user to confirm that they accept the agreement and want to download the file by clicking on a button outside the PDFViewer.</p><p>To achieve this requirement, you can handle the button&rsquo;s &ldquo;click&rdquo; event and initiate the download of the file that is currently displayed by the PDFViewer with the help of the available API.</p><ol><li>Hide the &ldquo;download&rdquo; tool by not including it in the <strong>Toolbar.Items</strong> collection:</li></ol><pre class=" language-csharp"><code class="prism  language-csharp"><span class="token punctuation">.</span><span class="token function">Toolbar</span><span class="token punctuation">(</span>toolbar <span class="token operator">=</span><span class="token operator">&gt;</span>
  toolbar<span class="token punctuation">.</span><span class="token function">Items</span><span class="token punctuation">(</span>items <span class="token operator">=</span><span class="token operator">&gt;</span>
  <span class="token punctuation">{</span>
    items<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Name</span><span class="token punctuation">(</span><span class="token string">"pager"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    items<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Name</span><span class="token punctuation">(</span><span class="token string">"spacer"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    items<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Name</span><span class="token punctuation">(</span><span class="token string">"zoom"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    items<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Name</span><span class="token punctuation">(</span><span class="token string">"zoomInOut"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    items<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Name</span><span class="token punctuation">(</span><span class="token string">"toggleSelection"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    items<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Name</span><span class="token punctuation">(</span><span class="token string">"spacer"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    items<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Name</span><span class="token punctuation">(</span><span class="token string">"search"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    items<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Name</span><span class="token punctuation">(</span><span class="token string">"open"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    items<span class="token punctuation">.</span><span class="token function">Add</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Name</span><span class="token punctuation">(</span><span class="token string">"print"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">)</span>
</code></pre><ol start="2"><li>The button that the user will click to confirm the agreement and start the download could look like this:</li></ol><pre class=" language-html"><code class="prism  language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>k-button k-button-solid-base k-button-solid k-button-md k-rounded-md<span class="token punctuation">"</span></span> <span class="token attr-name">onclick</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>onAgreeButtonClick()<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>Agree and Download PDF<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">&gt;</span></span>
</code></pre><ol start="3"><li>In the button&rsquo;s click handler, the download is triggered by executing the &ldquo;DownloadCommand&rdquo; of the PDFViewer:</li></ol><pre class=" language-html"><code class="prism  language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script language-javascript">
  <span class="token keyword">function</span> <span class="token function">onAgreeButtonClick</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token comment">// get a reference to the PDFViewer</span>
    <span class="token keyword">var</span> pdfviewer <span class="token operator">=</span> <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">"#pdfviewer"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">data</span><span class="token punctuation">(</span><span class="token string">"kendoPDFViewer"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token comment">// execute the Download command programmatically</span>
    pdfviewer<span class="token punctuation">.</span><span class="token function">execute</span><span class="token punctuation">(</span><span class="token punctuation">{</span>command<span class="token punctuation">:</span><span class="token string">"DownloadCommand"</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>
</code></pre><h2 id="working-with-larger-files">Working with Larger Files</h2><p>Finally, we will use a feature of the PDFViewer that allows you to load a large PDF document without sacrificing performance and causing the page to become unresponsive.</p><p>In scenarios that involve loading large PDF documents, use the load-on-demand functionality of the PDFViewer. It is available when the component is configured to use Telerik Document Processing.</p><p>The following snippet shows how to enable the <strong>LoadOnDemand</strong> option:</p><pre class=" language-csharp"><code class="prism  language-csharp">@<span class="token punctuation">(</span>Html<span class="token punctuation">.</span><span class="token function">Kendo</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">PDFViewer</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">Name</span><span class="token punctuation">(</span><span class="token string">"pdfviewer"</span><span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">DplProcessing</span><span class="token punctuation">(</span>dpl <span class="token operator">=</span><span class="token operator">&gt;</span> <span class="token punctuation">{</span>
    dpl<span class="token punctuation">.</span><span class="token function">Read</span><span class="token punctuation">(</span>r <span class="token operator">=</span><span class="token operator">&gt;</span> r<span class="token punctuation">.</span><span class="token function">Url</span><span class="token punctuation">(</span>Url<span class="token punctuation">.</span><span class="token function">Action</span><span class="token punctuation">(</span><span class="token string">"GetInitialPdf"</span><span class="token punctuation">,</span> <span class="token string">"PdfViewer"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    dpl<span class="token punctuation">.</span><span class="token function">Upload</span><span class="token punctuation">(</span>upload <span class="token operator">=</span><span class="token operator">&gt;</span> upload<span class="token punctuation">.</span><span class="token function">Url</span><span class="token punctuation">(</span>Url<span class="token punctuation">.</span><span class="token function">Action</span><span class="token punctuation">(</span><span class="token string">"GetPdf"</span><span class="token punctuation">,</span> <span class="token string">"PdfViewer"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">SaveField</span><span class="token punctuation">(</span><span class="token string">"file"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    dpl<span class="token punctuation">.</span><span class="token function">LoadOnDemand</span><span class="token punctuation">(</span><span class="token keyword">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
  <span class="token punctuation">.</span><span class="token function">Height</span><span class="token punctuation">(</span><span class="token number">900</span><span class="token punctuation">)</span>
<span class="token punctuation">)</span>
</code></pre><p>With the <strong>LoadOnDemand</strong> option enabled, instead of requesting and visualizing all the pages of the document, the component requests and renders pages on demand, which improves performance by reducing the initial load time.</p><p>If you&rsquo;re interested in learning more about the PDFViewer component, check out the folowing:</p><ul><li><a target="_blank" href="https://www.telerik.com/aspnet-core-ui/pdf-viewer">ASP.NET Core PDFViewer product page</a></li><li><a target="_blank" href="https://demos.telerik.com/aspnet-core/pdfviewer">ASP.NET Core PDFViewer demo</a></li><li><a target="_blank" href="https://docs.telerik.com/aspnet-core/html-helpers/pdf/pdfviewer/overview">ASP.NET Core PDFViewer documentation</a></li></ul><h2 id="try-out-the-telerik-ui-for-asp.net-core-pdfviewer-today">Try out the Telerik UI for ASP.NET Core PDFViewer Today</h2><p>If you like what you&rsquo;ve read and want to start taking advantage of the ASP.NET Core PDFViewer, or any of the other 110+ ready-made components, we invite you to start a free trial today. Experience firsthand that building rich interactive applications
    for half the time is just a click away.</p><p><a target="_blank" href="https://www.telerik.com/try/aspnet-core-ui" class="Btn">Try Telerik UI for ASP.NET Core</a></p><h2 id="sharing-is-caring">Sharing is Caring</h2><p>Once you try the ASP.NET Core PDFViewer component, don&rsquo;t forget to share your experience and ideas in the comments sections below or by visiting the <a target="_blank" href="https://feedback.telerik.com/aspnet-core-ui">Telerik UI for ASP.NET Core Feedback Portal</a>.
 Your input makes a difference.</p><img src="https://feeds.telerik.com/link/23072/16226674.gif" height="1" width="1"/>]]></content>
  </entry>
  <entry>
    <id>urn:uuid:dd5b0381-e978-4640-8a3f-76adc8fd92a4</id>
    <title type="text">Get Familiar with the New Page Numbering Fields in the WordsProcessing Library</title>
    <summary type="text">Have a look at the new Page Numbering fields in the WordsProcessing library and how to implement them.</summary>
    <published>2023-04-04T07:18:03Z</published>
    <updated>2026-04-11T21:18:52Z</updated>
    <author>
      <name>Yoan Karamanov </name>
    </author>
    <link rel="alternate" href="https://feeds.telerik.com/link/23072/16055934/get-familiar-new-page-numbering-fields-wordsprocessing-library"/>
    <content type="text"><![CDATA[<p><span class="featured">Have a look at the new Page Numbering fields in the WordsProcessing library and how to implement them.</span></p><p>In the <a href="https://www.telerik.com/blogs/r3-2022-telerik-desktop-mobile-release#telerik-document-processing-libraries" target="_blank">R3 2022 Release</a> for RadWordsProccessing from Progress <a target="_blank" href="https://www.telerik.com/document-processing-libraries">Telerik Document Processing Libraries</a>,
 we introduced support for five new page numbering type fields:
    <a href="https://docs.telerik.com/devtools/document-processing/libraries/radwordsprocessing/concepts/fields/page-field" target="_blank">Page</a>,
 <a href="https://docs.telerik.com/devtools/document-processing/libraries/radwordsprocessing/concepts/fields/pageref-field" target="_blank">PageRef</a>, <a href="https://docs.telerik.com/devtools/document-processing/libraries/radwordsprocessing/concepts/fields/numpages-fields" target="_blank">NumPages</a>,
 <a href="https://docs.telerik.com/devtools/document-processing/libraries/radwordsprocessing/concepts/fields/sectionpages-field" target="_blank">SectionPages</a> and <a href="https://docs.telerik.com/devtools/document-processing/libraries/radwordsprocessing/concepts/fields/section" target="_blank">Section</a>.</p><p>They are commonly used fields for inserting page numbering and their evaluation requires calculating the layout of the document and the size of the document elements. That calculation is done by the <a href="https://docs.telerik.com/devtools/document-processing/libraries/radwordsprocessing/concepts/fields/numbering-fields-provider" target="_blank">NumberingFieldsProvider</a>, which needs to be implemented in order to update the fields.</p><h2>Inserting Fields</h2><p>For the default implementation of the <a href="https://docs.telerik.com/devtools/document-processing/libraries/radwordsprocessing/concepts/fields/numbering-fields-provider" target="_blank">NumberingFieldsProvider</a> to work, the
    <em>Telerik.Documents.Flow.FormatProviders.Pdf.dll</em> assembly should be referenced in the project we are working with.</p><p>When it comes to inserting the fields in the document, the easiest and recommended way of doing that is via the <a href="https://docs.telerik.com/devtools/document-processing/libraries/radwordsprocessing/editing/radflowdocumenteditor" target="_blank">RadFlowDocumentEditor</a>&rsquo;s InsertField method.
</p><p>We will incorporate all this functionality in a simple project for you to see, but before that here is a brief overview of all the newly added fields:</p><ul><li>The <strong>PAGE</strong> field inserts the current page number.</li></ul><pre><code class="language-csharp">PAGE [*Format Switch]</code></pre><ul><li>The <strong>PAGEREF</strong> field inserts the page number of a bookmark for cross-reference.</li></ul><pre><code class="language-csharp">PAGEREF Bookmark [* Format Switch ] </code></pre><ul><li>The <strong>SECTION</strong> field inserts the number of the current section.</li></ul><pre><code class="language-csharp">SECTION</code></pre><ul><li>The <strong>SECTIONPAGES</strong> field inserts the total number of pages in a section.</li></ul><pre><code class="language-csharp">SECTIONPAGES</code></pre><ul><li>The <strong>NUMPAGES</strong> field inserts the total number of pages in the document.</li></ul><pre><code class="language-csharp">NUMPAGES</code></pre><p>Now let us go together through a couple of examples that demonstrate the implementation of some of those fields in an empty RadFlowDocument:</p><h3>Example 1: Page &amp; NumPages</h3><p>The first thing we need to do is create an empty document and a RadFlowDocumentEditor instance for that document, and then register the NumberingFieldsProvider:</p><pre><code class="language-csharp">RadFlowDocument document = new RadFlowDocument();
RadFlowDocumentEditor editor = new RadFlowDocumentEditor(document);

FlowExtensibilityManager.NumberingFieldsProvider = new NumberingFieldsProvider();</code></pre><p>From this point on, the implementation of the various page numbering fields is mostly similar, with a few differences in case we are utilizing the switches for formatting. For example, let&rsquo;s add text that shows the current page number out of the
    total number of pages. For this we will need the PAGE and NUMPAGES fields:</p><pre><code class="language-csharp">editor.InsertText("Page ");
editor.InsertField("PAGE", "");
editor.InsertText(" of ");
editor.InsertField("NUMPAGES", "");</code><br /></pre><p>When you are ready with the modifications of the document, you must ensure that the fields are updated, otherwise nothing will be visualized in their place. We can do that by calling the UpdateFields method of the document:</p><pre><code class="language-csharp">document.UpdateFields();</code><br /></pre><p>And after exporting the document the result that the above-provided code snippet produces should be &ldquo;Page 1 of 1.&rdquo;</p><h3>Example 2: PageRef</h3><p>Let&rsquo;s do the same thing but this time bring up the page number of a bookmark we have added. To achieve that, we will use the PAGEREF field with a formatting switch:</p><pre><code class="language-csharp">Bookmark bookmark = editor.InsertBookmark(&ldquo;MyBookmark");

editor.InsertText("Bookmark Page: ");
editor.InsertField("PAGEREF MyBookmark \h", "");

document.UpdateFields();</code><br /></pre><p>The &ldquo;\h&rdquo; switch in this case creates a hyperlink to the bookmarked paragraph and the final result ends up being &ldquo;Bookmark Page: 1.&rdquo;</p><p>If you are curious and want to find out more about the capabilities and functionality of those recently introduced fields as well as some other examples, you can head to the <a href="https://docs.telerik.com/devtools/document-processing/libraries/radwordsprocessing/concepts/fields/fields#fields" target="_blank">WordsProccessing: Fields documentation</a> and explore further.</p><h2>Try These New Features out &amp; Share Your Feedback with Us</h2><p>Regardless if you are new to Telerik <a href="https://docs.telerik.com/devtools/document-processing/introduction" target="_blank">Document Processing</a> or already a user, you can head over and <a href="https://www.telerik.com/download-trial-file/v2-b/devcraft-ultimate" target="_blank">download a free trial</a>.
 <a href="https://www.telerik.com/account/downloads" target="_blank">Your Telerik Account</a> provides access to the latest bits you might need, or you can just update the NuGet package references in your .NET solutions.</p><p>Each input we get, whether big or small, can make the huge difference we are looking for in our growth and progression. So please, feel welcome to look around and share your thoughts in our <a href="https://feedback.telerik.com/document-processing" target="_blank">Feedback Portal</a> or just leave a comment below about your experience.</p><img src="https://feeds.telerik.com/link/23072/16055934.gif" height="1" width="1"/>]]></content>
  </entry>
  <entry>
    <id>urn:uuid:3b0f219e-dda3-4535-9612-7283ba9348e0</id>
    <title type="text">Hand-Signing a PDF File Made Easy with RadSignature for ASP.NET AJAX</title>
    <summary type="text">The Telerik UI for ASP.NET AJAX RadSignature allows you to add a signature spot to PDFs and includes customization options like brush, stroke and background color. Learn how to add it to your PDF.</summary>
    <published>2023-02-24T08:33:03Z</published>
    <updated>2026-04-11T21:18:52Z</updated>
    <author>
      <name>Doncho Milkov </name>
    </author>
    <link rel="alternate" href="https://feeds.telerik.com/link/23072/15990754/hand-signing-pdf-file-made-easy-radsignature-aspnet-ajax"/>
    <content type="text"><![CDATA[<p><span class="featured">The Telerik UI for ASP.NET AJAX RadSignature allows you to add a signature spot to PDFs and includes customization options like brush, stroke and background color. Learn how to add it to your PDF.</span></p><p>In the world of digital signatures, the ability to sign PDF documents is a game changer. And with the <a href="https://www.telerik.com/products/aspnet-ajax/signature.aspx" target="_blank">RadSignature</a> component from Progress
    <a target="_blank" href="https://www.telerik.com/products/aspnet-ajax.aspx">Telerik UI for ASP.NET AJAX</a>, this process has never been easier!</p><p>Read on to find out how to effortlessly save a signature within a PDF file using the <a target="_blank" href="https://www.telerik.com/document-processing-libraries">Telerik Document Processing Libraries</a> (DPL) and to present the signed document in the RadPdfViewer control.</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2023/2023-02/1-telerik-ui-for-asp.net-ajax-signpdf-gif.gif?sfvrsn=bde33484_3" alt="User signs, hits Place button, and the signature appears on a certificate PDF"></p><p>Whether you&rsquo;re a developer wanting to integrate a digital signature into your project, or just looking to explore the world of digital signatures, this blog post is the perfect starting point.</p><p>Join us as we show you how to:</p><ul><li>Extract applied signature as PDF</li><li>Create a new PDF document that includes your signature</li><li>Load the signed document in a PdfViewer</li></ul><p>With the help of <a target="_blank" href="https://www.telerik.com/products/aspnet-ajax.aspx">Telerik UI for ASP.NET AJAX</a>, we&rsquo;ll demonstrate how to convert the
    signature content to PDF and base64 string representation. And the best part&mdash;you can preview the PDF file using the built-in <a href="https://www.telerik.com/products/aspnet-ajax/pdf-viewer.aspx" target="_blank">RadPdfViewer</a>,
 and even save the new document with the click of a button. So why wait? Let&rsquo;s dive into the world of digital signatures and explore the possibilities with RadSignature for ASP.NET AJAX.</p><h2 id="prerequisites">Prerequisites</h2><p>Let&rsquo;s start with declaring the needed controls on the page:</p><ol><li><a href="https://docs.telerik.com/devtools/aspnet-ajax/controls/signature/overview" target="_blank">RadSignature</a> is needed to apply the signature that we want to transfer to the PDF file.</li></ol><p><strong>ASPX</strong></p><pre class=" language-markup"><code class="prism  language-markup"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerik:</span>RadSignature</span>  <span class="token attr-name">runat</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>server<span class="token punctuation">"</span></span>  <span class="token attr-name">ID</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>RadSignature1<span class="token punctuation">"</span></span>  <span class="token attr-name">Maximizable</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>false<span class="token punctuation">"</span></span>  <span class="token attr-name">Height</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>150<span class="token punctuation">"</span></span>  <span class="token attr-name">Width</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>100%<span class="token punctuation">"</span></span>  <span class="token attr-name">Rounded</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>None<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span><span class="token namespace">telerik:</span>RadSignature</span><span class="token punctuation">&gt;</span></span>
</code></pre><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2023/2023-02/2-telerik-ui-for-asp.net-ajax-signature-gif.tmb-0.gif?Culture=en&amp;sfvrsn=b039ae26_1" alt="Signature is selected"></p><ol start="2"><li><a href="https://docs.telerik.com/devtools/aspnet-ajax/controls/pdfviewer/overview" target="_blank">RadPdfViewer</a> is needed to display the PDF file that we are currently working on while exposing some of its useful built-in
        features such as zoom, download, print, search, toggle selection and paging.</li></ol><p><strong>ASPX</strong></p><pre class=" language-markup"><code class="prism  language-markup"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerik:</span>RadPdfViewer</span> <span class="token attr-name">runat</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>server<span class="token punctuation">"</span></span> <span class="token attr-name">ID</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>RadPdfViewer1<span class="token punctuation">"</span></span> <span class="token attr-name">Height</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>700px<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>PdfjsProcessingSettings</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>FileSettings</span> <span class="token attr-name">Url</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Documents/Document.pdf<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>PdfjsProcessingSettings</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span><span class="token namespace">telerik:</span>RadPdfViewer</span><span class="token punctuation">&gt;</span></span>
</code></pre><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2023/2023-02/3-telerik-ui-for-asp.net-ajax-pdfviewer---overview.tmb-0.png?Culture=en&amp;sfvrsn=1b690ed_1" alt="PDF viewer"></p><p>In this sample, we are passing the unsigned PDF file by a relative path through the FileSettings of the PdfViewer. Yet, there are multiple other ways you can populate the Viewer. The most common ones you can find explained in the <a href="https://www.telerik.com/blogs/5-different-approaches-setting-up-content-radpdfviewer-aspnet-ajax" target="_blank">5 Different Approaches of Setting up the Content in RadPdfViewer for ASP.NET AJAX</a> blog post.</p><ol start="3"><li><a href="https://docs.telerik.com/devtools/aspnet-ajax/controls/toolbar/overview" target="_blank">RadToolBar</a> contains the needed buttons and color pickers which enable the users to customize the Signature appearance and
        align it to their personal preferences on their own.</li></ol><p><strong>ASPX</strong></p><pre class=" language-markup"><code class="prism  language-markup"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerik:</span>RadToolBar</span> <span class="token attr-name">runat</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>server<span class="token punctuation">"</span></span> <span class="token attr-name">ID</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>RadToolBar1<span class="token punctuation">"</span></span> <span class="token attr-name">AutoPostBack</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>false<span class="token punctuation">"</span></span> <span class="token attr-name">OnClientButtonClicked</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>clientToolBarButtonClicked<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>Items</span><span class="token punctuation">&gt;</span></span>
        ...
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>Items</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span><span class="token namespace">telerik:</span>RadToolBar</span><span class="token punctuation">&gt;</span></span>
</code></pre><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2023/2023-02/4-telerik-ui-for-asp.net-ajax-signature-toolbar-integration.tmb-0.png?Culture=en&amp;sfvrsn=9c1b6d55_1" alt="Toolbar with brush, stroke, background"></p><p>The ToolBar is not under the spotlight now, so we will not dig into its details now. It is here just to sweeten the UX of the demo.</p><ol start="4"><li><a href="https://docs.telerik.com/devtools/aspnet-ajax/controls/button/overview" target="_blank">RadButton</a> is needed to trigger the whole process prior to signing the document and previewing it.</li></ol><p><strong>ASPX</strong></p><pre class=" language-markup"><code class="prism  language-markup"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerik:</span>RadButton</span>  <span class="token attr-name">runat</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>server<span class="token punctuation">"</span></span>  <span class="token attr-name">ID</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>RadButton1<span class="token punctuation">"</span></span>  <span class="token attr-name">Text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Place Your Signature<span class="token punctuation">"</span></span>  <span class="token attr-name">Icon-PrimaryIconCssClass</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>rbSave<span class="token punctuation">"</span></span>  <span class="token attr-name">AutoPostBack</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>false<span class="token punctuation">"</span></span>  <span class="token attr-name">Primary</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span>  <span class="token attr-name">OnClientClicked</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>processSignature<span class="token punctuation">"</span></span>  <span class="token punctuation">/&gt;</span></span>
</code></pre><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2023/2023-02/5-telerik-ui-for-asp.net-ajax-signature-button-integration.png?sfvrsn=63163ebe_3" alt="Place your signature button"></p><p>Not all heroes wear capes, right? Just like that, not all components are on the front stage&mdash;some stay behind the scenes but are still needed:</p><ol start="5"><li><a href="https://docs.telerik.com/devtools/aspnet-ajax/controls/clientexportmanager/overview" target="_blank">RadClientExportManager</a> is required to export the applied signature into a PDF format and get its data as a base64
        string.
    </li></ol><p><strong>ASPX</strong></p><pre class=" language-markup"><code class="prism  language-markup"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerik:</span>RadClientExportManager</span>  <span class="token attr-name">runat</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>server<span class="token punctuation">"</span></span>  <span class="token attr-name">ID</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>RadClientExportManager1<span class="token punctuation">"</span></span>  <span class="token attr-name">OnClientPdfExporting</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>clientPdfExporting<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span><span class="token namespace">telerik:</span>RadClientExportManager</span><span class="token punctuation">&gt;</span></span>
</code></pre><ol start="6"><li><a href="https://docs.telerik.com/devtools/aspnet-ajax/controls/ajaxmanager/overview" target="_blank">RadAjaxManager</a> is there to improve the user experience by performing AJAX requests for passing the signature to the server
        and the manipulated pdf back to the browser.</li></ol><p><strong>ASPX</strong></p><pre class=" language-markup"><code class="prism  language-markup"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerik:</span>RadAjaxManager</span> <span class="token attr-name">ID</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>RadAjaxManager1<span class="token punctuation">"</span></span> <span class="token attr-name">runat</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>server<span class="token punctuation">"</span></span> <span class="token attr-name">OnAjaxRequest</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>RadAjaxManager1_AjaxRequest<span class="token punctuation">"</span></span> <span class="token attr-name">DefaultLoadingPanelID</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>RadAjaxLoadingPanel1<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>AjaxSettings</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerik:</span>AjaxSetting</span> <span class="token attr-name">AjaxControlID</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>RadAjaxManager1<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>UpdatedControls</span><span class="token punctuation">&gt;</span></span>
                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerik:</span>AjaxUpdatedControl</span> <span class="token attr-name">ControlID</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>RadPdfViewer1<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>UpdatedControls</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span><span class="token namespace">telerik:</span>AjaxSetting</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>AjaxSettings</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span><span class="token namespace">telerik:</span>RadAjaxManager</span><span class="token punctuation">&gt;</span></span>
</code></pre><ol start="7"><li><a href="https://docs.telerik.com/devtools/aspnet-ajax/controls/ajaxloadingpanel/overview" target="_blank">RadAjaxLoadingPanel</a> is needed to display a progress indicator graphic while processing the data on the server-side.</li></ol><p><strong>ASPX</strong></p><pre class=" language-markup"><code class="prism  language-markup"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerik:</span>RadAjaxLoadingPanel</span>  <span class="token attr-name">runat</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>server<span class="token punctuation">"</span></span>  <span class="token attr-name">ID</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>RadAjaxLoadingPanel1<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span><span class="token namespace">telerik:</span>RadAjaxLoadingPanel</span><span class="token punctuation">&gt;</span></span>
</code></pre><p>Alongside all the above-mentioned components, we will also need to reference the Telerik Document Processing Libraries (DPL) and specifically the RadPdfProcessing library assemblies necessary for manipulating the content of a PDF file. Find the list of
    the .dll files required for the RadPdfProcessing in the <a href="https://docs.telerik.com/devtools/document-processing/libraries/radpdfprocessing/overview" target="_blank">dedicated documentation page</a>.</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2023/2023-02/6-telerik-ui-for-asp.net-ajax-radpdfprocessing.tmb-0.png?Culture=en&amp;sfvrsn=2daa0194_1" alt="Illustration of a computer with RadPDFProcessing"></p><p>Once we have the components defined, the DPL referenced and the unsigned PDF loaded in the view, we can go ahead with the logic.</p><p>I bet you&rsquo;ve noticed that the event handlers we are going to use are already defined in the control snippets above. So, let&rsquo;s go through the process after the user has applied their signature and clicks the blue &ldquo;Place Your Signature&rdquo;
    button.
</p><h2 id="extract-applied-signature-as-pdf">Extract Applied Signature as PDF</h2><p>The <code class="inline-code">OnClientClicked</code> event of the button fires upon clicking the blue button. In its listener, we can get the canvas element with the applied signature with a bit of jQuery help, and also get the ClientExportManager client-side
    control. Via the <code class="inline-code">exportToPdf()</code> method of the export manager we can trigger exporting the canvas to a pdf:</p><p><strong>JavaScript</strong></p><pre class=" language-js"><code class="prism  language-js"><span class="token function-variable function">processSignature</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span>sender<span class="token punctuation">,</span> args<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token comment">//get the ClientExportManager client-side control object</span>
    <span class="token keyword">var</span> clientExportManager <span class="token operator">=</span> $telerik<span class="token punctuation">.</span><span class="token function">findControl</span><span class="token punctuation">(</span>document<span class="token punctuation">,</span> <span class="token string">"RadClientExportManager1"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token comment">//get the canvas element holding the applied signature</span>
    <span class="token keyword">var</span> signatureElement <span class="token operator">=</span> <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">".k-signature-canvas &gt; canvas"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token comment">//trigger exporting to pdf procedure via the built-in method of the ExportManager</span>
    clientExportManager<span class="token punctuation">.</span><span class="token function">exportPDF</span><span class="token punctuation">(</span>signatureElement<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><p>After that, the <code class="inline-code">OnClientPdfExporting</code> event of the export manager fires. Here we can get the PDF representation of the signature as a base64string directly from the event arguments (<code class="inline-code">get_dataURI()</code>).
 Get the AJAX manager and send an AJAX request to the server with the signature data optionally along with a custom file name:</p><p><strong>JavaScript</strong></p><pre class=" language-js"><code class="prism  language-js"><span class="token function-variable function">clientPdfExporting</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span>sender<span class="token punctuation">,</span> args<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token comment">//get the base64string of the pdf passed for exporting</span>
    <span class="token keyword">var</span> dataRaw <span class="token operator">=</span> args<span class="token punctuation">.</span><span class="token function">get_dataURI</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token comment">//get the RadAjaxManager control object</span>
    <span class="token keyword">var</span> ajaxManager <span class="token operator">=</span> $telerik<span class="token punctuation">.</span><span class="token function">findControl</span><span class="token punctuation">(</span>document<span class="token punctuation">,</span> <span class="token string">"RadAjaxManager1"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">var</span> fileName <span class="token operator">=</span> <span class="token string">"signature.png"</span><span class="token punctuation">;</span>
    <span class="token comment">//send an ajax request to the server with the signature data and the filename</span>
    ajaxManager<span class="token punctuation">.</span><span class="token function">ajaxRequest</span><span class="token punctuation">(</span>fileName <span class="token operator">+</span> <span class="token string">";"</span> <span class="token operator">+</span> dataRaw<span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token comment">//prevent further execution of the built-in exporting logic of the ExportManager</span>
    args<span class="token punctuation">.</span><span class="token function">set_cancel</span><span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><p>Once the request reaches the server, the AjaxRequest event of the RadAjaxManager fires. There we can get the base64 string of the signature and pass it to the function responsible for generating a signed PDF. Finally, pass the base64 string representation
    of the signed PDF as content of the PdfViewer.</p><p><strong>C#</strong></p><pre class=" language-csharp"><code class="prism  language-csharp"><span class="token keyword">protected</span> <span class="token keyword">void</span> <span class="token function">RadAjaxManager1_AjaxRequest</span><span class="token punctuation">(</span><span class="token keyword">object</span> sender<span class="token punctuation">,</span> Telerik<span class="token punctuation">.</span>Web<span class="token punctuation">.</span>UI<span class="token punctuation">.</span>AjaxRequestEventArgs e<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
    <span class="token keyword">var</span> base64 <span class="token operator">=</span> e<span class="token punctuation">.</span>Argument<span class="token punctuation">.</span><span class="token function">Split</span><span class="token punctuation">(</span><span class="token string">','</span><span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">;</span>

    RadPdfViewer1<span class="token punctuation">.</span>PdfjsProcessingSettings<span class="token punctuation">.</span>FileSettings<span class="token punctuation">.</span>Data <span class="token operator">=</span> <span class="token function">PreparePdf</span><span class="token punctuation">(</span>base64<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><h2 id="create-a-new-pdf-document-that-includes-your-signature">Create a New PDF Document That Includes Your Signature</h2><p>Let&rsquo;s explore the exact purpose of the <code class="inline-code">PreparePdf()</code> method.</p><p>With the help of the Document Processing Libraries (DPL), we can easily generate an all-new copy of the unsigned PDF document that we have. Then we can append the signature content we already extracted into the new Pdf document at a desired position.</p><p><strong>C#</strong></p><pre class=" language-csharp"><code class="prism  language-csharp"><span class="token keyword">public</span> <span class="token keyword">string</span> <span class="token function">PreparePdf</span><span class="token punctuation">(</span><span class="token keyword">string</span> pdfData<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
    <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> resultingBytes <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
    <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> finalBytes <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span>

    <span class="token comment">//initialize a PdfFormatProvider that will be used for processing the pdf conent</span>
    PdfFormatProvider provider <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">PdfFormatProvider</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> renderedBytes <span class="token operator">=</span> Convert<span class="token punctuation">.</span><span class="token function">FromBase64String</span><span class="token punctuation">(</span>pdfData<span class="token punctuation">)</span><span class="token punctuation">;</span>

    RadFixedDocument document1 <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
    <span class="token comment">//generate a RadFixedDocument object holding the signature data</span>
    RadFixedDocument document2 <span class="token operator">=</span> provider<span class="token punctuation">.</span><span class="token function">Import</span><span class="token punctuation">(</span>renderedBytes<span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token comment">//import the existing unsigned pdf file in another RadFixedDocument </span>
    <span class="token keyword">string</span> filePath <span class="token operator">=</span> Server<span class="token punctuation">.</span><span class="token function">MapPath</span><span class="token punctuation">(</span><span class="token string">"Documents/Document.pdf"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">using</span> <span class="token punctuation">(</span>FileStream input <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">FileStream</span><span class="token punctuation">(</span>filePath<span class="token punctuation">,</span> FileMode<span class="token punctuation">.</span>Open<span class="token punctuation">,</span> FileAccess<span class="token punctuation">.</span>Read<span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        document1 <span class="token operator">=</span> provider<span class="token punctuation">.</span><span class="token function">Import</span><span class="token punctuation">(</span>input<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token comment">//export the unsigned pdf as byte array</span>
    <span class="token keyword">using</span> <span class="token punctuation">(</span>MemoryStream ms <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">MemoryStream</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        provider<span class="token punctuation">.</span><span class="token function">Export</span><span class="token punctuation">(</span>document1<span class="token punctuation">,</span> ms<span class="token punctuation">)</span><span class="token punctuation">;</span>
        resultingBytes <span class="token operator">=</span> ms<span class="token punctuation">.</span><span class="token function">ToArray</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token comment">//pass the byte array of the unsigned pdf and the RadFixedDocument with the applied signature to method that will combine them in a single byte array</span>
    finalBytes <span class="token operator">=</span> <span class="token function">AppendContent</span><span class="token punctuation">(</span>resultingBytes<span class="token punctuation">,</span> document2<span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token comment">//convert the result to a base64 string and return it so it can be passed as content of the PdfViewer</span>
    <span class="token keyword">string</span> result <span class="token operator">=</span> Convert<span class="token punctuation">.</span><span class="token function">ToBase64String</span><span class="token punctuation">(</span>finalBytes<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> result<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><p>The actual manipulation of the PDF content happens in the <code class="inline-code">AppendContent()</code> method. Its logic heavily relies on the functionalities exposed by the <a href="https://docs.telerik.com/devtools/document-processing/libraries/radpdfprocessing/overview" target="_blank">RadPdfProcessing library</a>:</p><p><strong>C#</strong></p><pre class=" language-csharp"><code class="prism  language-csharp"><span class="token keyword">private</span> <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token function">AppendContent</span><span class="token punctuation">(</span><span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> resultingBytes<span class="token punctuation">,</span> RadFixedDocument document2<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
    RadFixedPage foregroundContentOwner <span class="token operator">=</span> document2<span class="token punctuation">.</span>Pages<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">;</span>

    MemoryStream ms <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">MemoryStream</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> renderedBytes <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
    <span class="token keyword">using</span> <span class="token punctuation">(</span>MemoryStream stream <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">MemoryStream</span><span class="token punctuation">(</span>resultingBytes<span class="token punctuation">)</span><span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        <span class="token keyword">using</span> <span class="token punctuation">(</span>PdfFileSource fileSource <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">PdfFileSource</span><span class="token punctuation">(</span>stream<span class="token punctuation">)</span><span class="token punctuation">)</span>
        <span class="token punctuation">{</span>
            <span class="token keyword">using</span> <span class="token punctuation">(</span>PdfStreamWriter fileWriter <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">PdfStreamWriter</span><span class="token punctuation">(</span>ms<span class="token punctuation">,</span> <span class="token keyword">true</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
            <span class="token punctuation">{</span>
                <span class="token keyword">foreach</span> <span class="token punctuation">(</span>PdfPageSource pageSource <span class="token keyword">in</span> fileSource<span class="token punctuation">.</span>Pages<span class="token punctuation">)</span>
                <span class="token punctuation">{</span>
                    <span class="token keyword">using</span> <span class="token punctuation">(</span>PdfPageStreamWriter pageWriter <span class="token operator">=</span> fileWriter<span class="token punctuation">.</span><span class="token function">BeginPage</span><span class="token punctuation">(</span>pageSource<span class="token punctuation">.</span>Size<span class="token punctuation">,</span> pageSource<span class="token punctuation">.</span>Rotation<span class="token punctuation">)</span><span class="token punctuation">)</span>
                    <span class="token punctuation">{</span>
                        pageWriter<span class="token punctuation">.</span><span class="token function">WriteContent</span><span class="token punctuation">(</span>pageSource<span class="token punctuation">)</span><span class="token punctuation">;</span>

                        <span class="token keyword">using</span> <span class="token punctuation">(</span>pageWriter<span class="token punctuation">.</span><span class="token function">SaveContentPosition</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
                        <span class="token punctuation">{</span>
                            <span class="token keyword">double</span> xCenteringTranslation <span class="token operator">=</span> <span class="token punctuation">(</span>pageSource<span class="token punctuation">.</span>Size<span class="token punctuation">.</span>Width <span class="token operator">-</span> foregroundContentOwner<span class="token punctuation">.</span>Size<span class="token punctuation">.</span>Width<span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token number">320</span><span class="token punctuation">;</span>
                            <span class="token keyword">double</span> yCenteringTranslation <span class="token operator">=</span> <span class="token punctuation">(</span>pageSource<span class="token punctuation">.</span>Size<span class="token punctuation">.</span>Height <span class="token operator">-</span> foregroundContentOwner<span class="token punctuation">.</span>Size<span class="token punctuation">.</span>Height<span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token number">110</span><span class="token punctuation">;</span>
                            pageWriter<span class="token punctuation">.</span>ContentPosition<span class="token punctuation">.</span><span class="token function">Translate</span><span class="token punctuation">(</span>xCenteringTranslation<span class="token punctuation">,</span> yCenteringTranslation<span class="token punctuation">)</span><span class="token punctuation">;</span>
                            pageWriter<span class="token punctuation">.</span><span class="token function">WriteContent</span><span class="token punctuation">(</span>foregroundContentOwner<span class="token punctuation">)</span><span class="token punctuation">;</span>
                        <span class="token punctuation">}</span>
                    <span class="token punctuation">}</span>
                <span class="token punctuation">}</span>
            <span class="token punctuation">}</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
    renderedBytes <span class="token operator">=</span> ms<span class="token punctuation">.</span><span class="token function">ToArray</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> renderedBytes<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><p>We will not go through each separate class and method of the DPL that is used, but I highly recommend spending some time getting familiar with the RadPdfProcessing <a href="https://docs.telerik.com/devtools/document-processing/libraries/radpdfprocessing/model" target="_blank">Model</a> and <a href="https://docs.telerik.com/devtools/document-processing/libraries/radpdfprocessing/concepts" target="_blank">Concepts</a>.</p><p>Everything written here is live and accessible <a href="https://demos.telerik.com/aspnet-ajax/signature/applicationscenarios/signingpdfdocuments/defaultcs.aspx" target="_blank">in this demo</a>. Go on and give it a try right away!</p><p>If you like what you see, you can further play with the RadSignature in <a href="https://demos.telerik.com/aspnet-ajax/signature/overview/defaultcs.aspx" target="_blank">the online demos</a> or download its <a href="https://www.telerik.com/download-trial-file/v2-b/ui-for-asp.net-ajax?_ga=2.57295843.874599603.1597651222-426342040.1588420200" target="_blank">absolutely free and fully functional trial</a> and give it a spin.</p><p>We value any feedback and the community voice, which you can share at <a href="https://feedback.telerik.com/aspnet-ajax" target="_blank">the Feedback Portal too</a>.</p><p><a href="https://www.telerik.com/download-trial-file/v2-b/ui-for-asp.net-ajax?_ga=2.57295843.874599603.1597651222-426342040.1588420200" target="_blank" class="Btn">Start a Free Trial</a></p><img src="https://feeds.telerik.com/link/23072/15990754.gif" height="1" width="1"/>]]></content>
  </entry>
  <entry>
    <id>urn:uuid:b7d1be99-833d-416c-ab0c-916a57eef4a7</id>
    <title type="text">Turn PDF Pages Into Images With PdfProcessing</title>
    <summary type="text">Check out the new functionality of Telerik PdfProcessing to convert PDF pages to images.</summary>
    <published>2022-12-15T14:17:02Z</published>
    <updated>2026-04-11T21:18:52Z</updated>
    <author>
      <name>Tanya Dimitrova </name>
    </author>
    <link rel="alternate" href="https://feeds.telerik.com/link/23072/15847443/turn-pdf-pages-images-pdfprocessing"/>
    <content type="text"><![CDATA[<p><span class="featured">Check out the new functionality of Telerik PdfProcessing to convert PDF pages to images.</span></p><p>Many of you requested us to provide you with the ability to export your documents or parts of them to images in .NET Standard/.NET Core applications. As we are always listening to your feedback, during the last release we worked hard to provide you with
    this functionality and I will present it in this blog post.</p><p>To make it possible for all platforms using the .NET Standard version of <a href="https://docs.telerik.com/devtools/document-processing/libraries/radpdfprocessing/overview" target="_blank">PdfProcessing</a> to create images, the
    library uses a third-party tool for image generation&mdash;<a href="https://docs.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/graphics/skiasharp/" target="_blank">SkiaSharp</a>. Multiple image formats are supported,
    and you can also choose whether to perform the exporting operation synchronously or asynchronously.</p><p>Let&rsquo;s take a closer look at the API related to the new functionality. The entry point making all the magic is the SkiaImageFormatProvider class. If you are already using PdfProcessing, you should be familiar with the <a href="https://docs.telerik.com/devtools/document-processing/libraries/radpdfprocessing/formats-and-conversion/pdf/pdfformatprovider/pdfformatprovider" target="_blank">format providers</a> and how they work. For all the rest, in short, the format providers expose Import and Export methods that enable you to parse a document into the internal model of the library or save the
    information from this model into a document file, respectively.</p><h2>Let&rsquo;s Create an Example</h2><p>To better demonstrate the functionality and its usage, I will guide you step by step on creating an application that opens an existing PDF document and converts its pages into images. </p><p>First things first&mdash;I will create a console application and add the dependencies we need to use the PdfProcessing library. For more convenience, I will directly go with the <strong>Telerik.Documents.Fixed.FormatProviders.Image.Skia</strong> NuGet
    package that will download all of its dependencies automatically:</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/2017-06/telerik.documents.fixed.formatproviders.image.skia-nuget-package-.png?sfvrsn=46d7d2e2_1" alt="Telerik.Documents.Fixed.FormatProviders.Image.Skia NuGet package in Visual Studio NuGet Manager" sf-size="100" /></p><p>In case you prefer adding references to the .dll files, here is the list of required assemblies:</p><ul><li>Telerik.Documents.Core</li><li>Telerik.Documents.Fixed</li><li>Telerik.Zip</li><li>Telerik.Documents.Fixed.FormatProviders.Image.Skia</li></ul><p>As I mentioned earlier, the image exporting functionality depends on SkiaSharp, thus you will need to add dependencies to its binaries as well:</p><ul><li>The <strong>SkiaSharp</strong> NuGet package</li><li>The <strong>SkiaSharp.NativeAssets.*</strong> NuGet package. This package may differ according to the used platform. There are versions for Windows, MacOS, Linux, WebAssembly, Android, iOS and others.</li></ul><p>Once we are ready with the setup, we can continue to add some logic to our application. The first step we need to implement is to read the PDF document we already have:</p><pre><code class="language-csharp">byte[] fileBytes = File.ReadAllBytes("SampleDocument.pdf");
 
Telerik.Windows.Documents.Fixed.FormatProviders.Pdf.PdfFormatProvider pdfFormatProvider = new Telerik.Windows.Documents.Fixed.FormatProviders.Pdf.PdfFormatProvider();
Telerik.Windows.Documents.Fixed.Model.RadFixedDocument fixedDocument = pdfFormatProvider.Import(fileBytes);
</code></pre><p>After having the document imported, you can now convert its pages to images through the Export method. In this example, each page is saved in a separate file.</p><pre><code class="language-csharp">SkiaImageFormatProvider imageProvider = new SkiaImageFormatProvider();
 
foreach (RadFixedPage page in fixedDocument.Pages)
{
    byte[] resultImage = imageProvider.Export(page);
    int pageNumber = fixedDocument.Pages.IndexOf(page) + 1;
    File.WriteAllBytes(@"C:\Temp\Images " + pageNumber + ".png", resultImage);
}
</code></pre><p>That is all you need to do if you need to read an existing file and export its pages to images. Check out the <a href="https://docs.telerik.com/devtools/document-processing/libraries/radpdfprocessing/formats-and-conversion/convert-to-image/using-image-format-provider" target="_blank">SkiaImageFormatProvider </a>documentation article if you are curious about other export settings. I hope you will enjoy the new functionality!</p><h2>Try Out the New Feature &amp; Share Your Feedback</h2><p>Head over and <a href="https://www.telerik.com/download-trial-file/v2-b/devcraft-ultimate" target="_blank">download a free trial</a>. If you are an active license holder, you can grab the latest bits from <a href="https://www.telerik.com/account/downloads" target="_blank">Your Telerik Account</a> or update your NuGet package references to the latest ones directly in your .NET solutions.</p><p>Share your thoughts with us on our <a href="https://feedback.telerik.com/document-processing" target="_blank">Feedback Portal</a> and help us shape the future of Telerik Document Processing!</p><img src="https://feeds.telerik.com/link/23072/15847443.gif" height="1" width="1"/>]]></content>
  </entry>
  <entry>
    <id>urn:uuid:d886db59-0dc9-4e19-939b-2b69c02c1e7a</id>
    <title type="text">Import Comes to the RadSpreadStreamProcessing Library in R3 2022</title>
    <summary type="text">See how to use the new import feature of the RadSpreadStreamProcessing library.</summary>
    <published>2022-11-21T08:03:00Z</published>
    <updated>2026-04-11T21:18:52Z</updated>
    <author>
      <name>Dimitar Karamfilov </name>
    </author>
    <link rel="alternate" href="https://feeds.telerik.com/link/23072/15799820/import-comes-radspreadstreamprocessing-library-r3-2022"/>
    <content type="text"><![CDATA[<p><span class="featured">See how to use the new import feature of the RadSpreadStreamProcessing library.</span></p><p>For a long time, we have supported creating files with the RadSpreadStreamProcessing library. This library is used particularly for large files. The key part is that it does not require all the data to be loaded in the application memory to create the
    document. This significantly reduces the memory usage of the application and allows for handling large amounts of data. This is achieved by directly writing the data in the file.</p><p>In the <a href="https://www.telerik.com/blogs/r3-2022-telerik-desktop-mobile-release#telerik-document-processing-libraries" target="_blank">R3 2022 Release</a>, we have added the ability for reading XLSX or CSV files with this
    library as well. This feature uses the same approach and reads the cells and properties consecutively (as they appear in the document structure). This way, only one cell is stored at a time in the application, which reduces the memory footprint. </p><p>Besides cell values, you can read the cell format and styles. You can read the Row/Column properties as well. Check out the <a href="https://docs.telerik.com/devtools/document-processing/libraries/radspreadstreamprocessing/import" target="_blank">Import </a>section of the RadSpreadStreamProcessing online documentation.</p><h2>An Example</h2><p>In the example below, we will use both features (reading and writing). In this scenario, we will have a very large XLSX file, and we want to use only some of the data inside. We will get the data depending on some cell properties. As we are reading the
    data, we will simultaneously write it in a CSV file. The resulting file will contain only the filtered data.</p><pre><code class="language-csharp">using Telerik.Documents.SpreadsheetStreaming;
string source = @"..\..\..\source.xlsx";
string result = @"..\..\..\result.csv";

using (FileStream sourceFile = File.OpenRead(source))
{
    using (FileStream resultFile = File.OpenWrite(result))
    {
        using (IWorkbookImporter workBookImporter = SpreadImporter.CreateWorkbookImporter(SpreadDocumentFormat.Xlsx, sourceFile))
        {
            using (IWorkbookExporter workbookExporter = SpreadExporter.CreateWorkbookExporter(SpreadDocumentFormat.Csv, resultFile))
            {
                using (IWorksheetImporter worksheetImporter = workBookImporter.WorksheetImporters.First())
                {
                    using (IWorksheetExporter worksheetExporter = workbookExporter.CreateWorksheetExporter("My sheet"))
                    {
                        foreach (IRowImporter rowImporter in worksheetImporter.Rows)
                        {
                            // Skip the header rows  
                            List&lt;string&gt; values = new List&lt;string&gt;();

                            foreach (ICellImporter cellImporter in rowImporter.Cells)
                            {
                                if (cellImporter.RowIndex &lt; 3)
                                {
                                    continue;
                                }

                                string value = cellImporter.Value;

                                if (cellImporter.ColumnIndex &lt;= 6 &amp;&amp; !string.IsNullOrEmpty(value))
                                {
                                    values.Add(value);
                                }

                                // Status column which is a color
                                else if (cellImporter.ColumnIndex == 7)
                                {
                                    var fill = cellImporter.Format.Fill as SpreadPatternFill;
                                    SpreadColor color = fill.BackgroundColor.LocalValue;

                                    // Export the rows with Green status only
                                    if (color.R == 142 &amp;&amp; color.G == 188 &amp;&amp; color.B == 0)
                                    {
                                        using (IRowExporter rowExporter = worksheetExporter.CreateRowExporter())
                                        {
                                            foreach (var item in values)
                                            {
                                                using (ICellExporter cellExporter = rowExporter.CreateCellExporter())
                                                {
                                                    cellExporter.SetValue(item);
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
</code></pre><p>I hope this example is useful. Converting the opposite scenario (CSV to XLSX) is supported as well and can be easily achieved. </p><h2>Try It and Share Your Feedback</h2><p>No matter if you are already familiar with <a href="https://docs.telerik.com/devtools/document-processing/introduction" target="_blank">Telerik Document Processing</a> or will meet the libraries for the first time, hurry up and
    get the latest bits so you can take advantage of the different document management possibilities they provide:</p><p><a href="https://www.telerik.com/download-trial-file/v2-b/devcraft-ultimate" target="_blank" class="Btn">Download a Free Trial</a></p><p>And hopefully you know by now that your input is valuable&mdash;we do listen. So, do not be shy and drop us a line to share your feedback in the comments section below or directly in our <a href="https://feedback.telerik.com/document-processing" target="_blank">Document Processing Libraries Feedback Portal</a>.</p><img src="https://feeds.telerik.com/link/23072/15799820.gif" height="1" width="1"/>]]></content>
  </entry>
  <entry>
    <id>urn:uuid:53477106-2554-4712-b6aa-4811356e459b</id>
    <title type="text">What’s New in Telerik Desktop &amp; Mobile With R3 2022</title>
    <summary type="text">Telerik Mobile and Desktop products offer expanded .NET 7 support, improved Document Processing Library features, and new components!</summary>
    <published>2022-09-14T14:58:06Z</published>
    <updated>2026-04-11T21:18:52Z</updated>
    <author>
      <name>Yoan Krumov </name>
    </author>
    <link rel="alternate" href="https://feeds.telerik.com/link/23072/15640890/r3-2022-telerik-desktop-mobile-release"/>
    <content type="text"><![CDATA[<p><span class="featured">Telerik Mobile and Desktop products offer expanded .NET 7 support, improved Document Processing Library features and new components!</span></p><p>As with every release, we are eager to share what the new updates are, so let&rsquo;s jump right in! Hop to your favorite section:
</p><ul><li><a href="https://www.telerik.com#telerik-ui-for-winui" data-sf-ec-immutable="">Telerik UI for WinUI</a></li><li><a href="https://www.telerik.com#telerik-ui-for-wpf" data-sf-ec-immutable="">Telerik UI for WPF</a></li><li><a href="https://www.telerik.com#telerik-ui-for-winforms" data-sf-ec-immutable="">Telerik UI for WinForms</a></li><li><a href="https://www.telerik.com#telerik-document-processing-libraries" data-sf-ec-immutable="">Telerik Document Processing Libraries</a></li><li><a href="https://www.telerik.com#telerik-ui-for-net-maui" data-sf-ec-immutable="">Telerik UI for .NET MAUI</a></li><li><a href="https://www.telerik.com#telerik-ui-for-xamarin" data-sf-ec-immutable="">Telerik UI for Xamarin</a></li><li><a href="https://www.telerik.com#telerik-net-web-desktop-mobile-products-webinar" data-sf-ec-immutable="">Terlerik .NET Web, Desktop &amp; Mobile Webinar &amp; Twitch Sessions</a></li></ul><h2 id="telerik-ui-for-winui">What&rsquo;s New in Telerik UI for WinUI 2.2.0</h2><h3 id="propertygrid">PropertyGrid</h3><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2022/2022-09/propertygrid.png?sfvrsn=75e1a662_3" title="PropertyGrid" alt="PropertyGrid" /></p><p>Announcing the <strong>RadPropertyGrid</strong> component for WinUI! The control provides an easy and versatile approach to processing data objects&rsquo; properties. Utilizing its auto-generation features and the intuitive custom editor capabilities,
    users will be able either to display data in a way that best fits their needs or modify it with minimal effort.</p><p><strong>RadPropertyGrid</strong> can be bound to an item with just a single line of code, and you may start exploring or editing its properties. The proper editor controls are auto-generated&mdash;text fields for string properties, CheckBoxes for Boolean,
    DateTimePickers for dates, etc. In addition, PropertyGrid allows flexible manual setting and customization of editors and their layout via the standard WinUI styling and templating mechanisms. It is highly customizable, allowing the user to modify
    the default look in an easy and intuitive manner.</p><p>Check out the key features below:</p><ul><li><strong>Automatic property generation</strong>&nbsp;&ndash; the control generates fields to read/write all public properties of the target object</li><li><strong>Built-in property editors</strong> &ndash; predefined editors UI for the different data types</li><li><strong>Nested properties support</strong></li><li><strong>Customizable property fields</strong> &ndash; customize the property definitions and the corresponding data editors</li><li><strong>Keyboard support</strong></li><li><strong>Grouping</strong></li><li><strong>Filtering</strong></li><li><strong>Data validation</strong></li></ul><p>For more information about the control, make sure to check out the <a href="https://docs.telerik.com/devtools/winui/controls/radpropertygrid/overview" target="_blank">PropertyGrid section</a> in our online help documentation.</p><h3 id="collectioneditor--collectioneditorpicker">CollectionEditor &amp; CollectionEditorPicker</h3><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2022/2022-09/collectioneditor.png?sfvrsn=8ddfaf2b_3" title="CollectionEditor" alt="CollectionEditor" /></p><p><strong>RadCollectionEditor</strong> and <strong>RadCollectionEditorPicker</strong> are two small components used to visualize the items in a collection and generate editors for each property using the built-in PropertyGrid component. You can use
        the ItemTemplate of the control to specify how the items from the collection should appear. The difference between them is that the <strong>CollectionEditorPicker</strong> uses a dropdown to display the <strong>CollectionEditor</strong>.</p><p>For more details, check out the <a href="https://docs.telerik.com/devtools/winui/controls/radcollectioneditor/overview" target="_blank">CollectionEditor section</a> in our help documentation.</p><h3 id="collectionnavigator">CollectionNavigator</h3><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2022/2022-09/collectionnavigator.png?sfvrsn=a8119512_3" title="CollectionNavigator" alt="CollectionNavigator" /></p><p><strong>RadCollectionNavigator</strong> is the next new control this release. A light component that provides seamless navigation and editing of a collection, it provides built-in customizable commands, predefined customizable buttons and more. For
        more details, make sure to check out the <a href="https://docs.telerik.com/devtools/winui/controls/radcollectionnavigator/overview" target="_blank">CollectionNavigator</a> section from our online help documentation.</p><h3 id="datagrid-export">DataGrid: Export</h3><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2022/2022-09/datagrid-export.png?sfvrsn=6aca6e65_3" title="DataGrid-Export" alt="DataGrid-Export" /></p><p>Our DataGrid gets export support&mdash;thanks to the Telerik <a href="https://www.telerik.com/document-processing-libraries" target="_blank">Document Processing Libraries</a> that are included in the WinUI distribution. The new functionality provides methods to export the current dataset displayed in the control. You can export in a synchronous or an async manner, modify the exported data and the final document.
            Currently the built-in export supports the following formats:</p><ul><li><strong>XLS</strong></li><li><strong>XLSX</strong></li><li><strong>PDF</strong></li><li><strong>CSV</strong></li></ul><p>Hope this feature will be useful. For more details, check out the <a href="https://docs.telerik.com/devtools/winui/controls/raddatagrid/export/overview" target="_blank">Export section</a> from our DataGrid documentation.</p><h3 id="ribbonview--other-updated-windows-11-appearance">RibbonView &amp; Other: Updated Windows 11 Appearance</h3><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2022/2022-09/ribbonview-light.png?sfvrsn=c9c4660d_3" title="RibbonView-Light" alt="RibbonView-Light" /></p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2022/2022-09/ribbonview-dark.png?sfvrsn=909eba37_3" title="RibbonView-Dark" alt="RibbonView-Dark" /></p><p>In this release, we did many improvements in the default styles of many controls to provide a better Windows 11 look and feel. Now I want to focus on the <a href="https://docs.telerik.com/devtools/winui/controls/radribbonview/overview" target="_blank">RibbonView</a> control&mdash;we completely redesigned it to resemble the <a href="https://support.microsoft.com/en-us/office/the-new-look-of-office-a6cdf19a-b2bd-4be1-9515-d74a37aa59bf" target="_blank">new Office 365 Experience</a>!
 It looks totally awesome and I&rsquo;m sure it will improve the overall appearance of your modern WinUI application. </p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2022/2022-09/winui-examples.png?sfvrsn=f7cf2042_3" title="WinUI-Examples" alt="WinUI-Examples" /></p><p>Make sure to check out the controls in our refreshed <a href="https://demos.telerik.com/winui/" target="_blank">WinUI examples application</a> and play around with them.</p><h3 id="other-features">Other Features</h3><ul><li><strong>SideDrawer</strong>: Added <a href="https://docs.telerik.com/devtools/winui/controls/radsidedrawer/events" target="_blank">DrawerOpening and DrawerClosing</a></li><li><strong>SideDrawer</strong>: Introduced <a href="https://docs.telerik.com/devtools/winui/controls/radsidedrawer/key-properties" target="_blank">IsOpen property</a></li></ul><h3 id="check-out-the-detailed-release-notes">Check Out the Detailed Release Notes</h3><p>We have a lot more! To get an overview of all the latest features and improvements we&rsquo;ve made, check out the release notes for the products below:</p><p><a href="https://www.telerik.com/support/whats-new/winui/release-history" target="_blank">Telerik UI for WinUI (Release Notes)</a></p><h3 id="share-your-feedback">Share Your Feedback</h3><ul><li><strong>Get in touch by email</strong> &ndash; drop us a line, for anything related to product or just to say hi at <a href="https://www.telerik.commailto:TelerikWinUI@progress.com" target="_blank">TelerikWinUI@progress.com</a></li><li><a href="https://feedback.telerik.com/winui" target="_blank"><strong>Feedback Portal</strong></a> &ndash; share any feature request (or bug reports) that you might have</li><li><a href="https://www.telerik.com/forums/winui" target="_blank"><strong>Telerik Forums</strong></a> &ndash; if you need any technical assistance with the product, let us know and we will help</li></ul><h3 id="get-the-bits">Get the Bits</h3><p>Don&rsquo;t wait&mdash;try out the latest:</p><p><a href="https://www.telerik.com/winui" class="Btn" target="_blank">Telerik UI for WinUI</a></p><p><em>In case you missed it, here are some of the updates from our <a href="https://www.telerik.com/blogs/telerik-kendo-ui-june-2022-update#whats-new-in-r2-2022-sp-for-telerik-ui-for-winui-2.1.0" target="_blank">previous release</a>.</em></p><h2 id="telerik-ui-for-wpf">What&rsquo;s New in Telerik UI for WPF With R3 2022</h2><h3 id="circularprogressbar">CircularProgressBar</h3><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2022/2022-09/circularprogressbar.png?sfvrsn=32c5ec1d_3" title="CircularProgressBar" alt="CircularProgressBar" /></p><p>Announcing our brand-new WPF <strong>CircularProgressBar</strong> component. <strong>CircularProgressBar</strong> is a control that will allow your customers to track the progress of different tasks in a circular manner. It provides many
                    customization options that will allow you to achieve a lot of different scenarios. You have probably seen such components in many different places&mdash;from health tracking smartphone applications to automatic coffee machines. 
                    Now you can easily plug it in your Telerik WPF application as well!</p><p>Check out the list of the major features of the control below:</p><ul><li><strong>Segments</strong>&nbsp;&ndash; CircularProgressBar can be split into numerous segments to indicate different types of progress.</li><li><strong>Color Ranges</strong>&nbsp;&ndash; CircularProgressBar supports defining ranges with different colors.</li><li><strong>Determinate and indeterminate states</strong>&nbsp;&ndash; The determinate state shows a specific amount of the progress. The indeterminate one plays an animation of the circular progress.</li><li><strong>Customizable content</strong>&nbsp;&ndash; CircularProgressBar supports complex implementation for the content of its progress.</li><li><strong>Radius manipulation</strong>&nbsp;&ndash; The control allows you to customize the indicator and track inner and outer radiuses.</li><li><strong>Angles</strong>&nbsp;&ndash; You can control the beginning and ending angles of the component for a more customized appearance.</li><li><strong>Secondary progress indicator</strong>&nbsp;&ndash; CircularProgressBar allows you to visualize an additional progress indicator.</li><li><strong>Indeterminate animation customization</strong>&nbsp;&ndash; You can modify the played animation when CircularProgressBar is in an indeterminate state.</li></ul><p>I hope this control will be useful in various types of applications. For more information, check out our online <a href="https://docs.telerik.com/devtools/wpf/controls/radcircularprogressbar/overview" target="_blank">CircularProgressBar help documentation</a>.</p><h3 id="pivotgrid-configuring-pivotgrid-without-pivotfieldlist">PivotGrid: Configuring PivotGrid Without PivotFieldList</h3><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2022/2022-09/pivot-inlinefieldlist.png?sfvrsn=4f6640ba_3" title="Pivot-InlineFieldList" alt="Pivot-InlineFieldList" /></p><p>The most desired PivotGrid feature is finally here! It allows using the control without the additional <strong>PivotFieldList</strong> control. The new functionality provides support of all existing PivotFieldList features&mdash;directly
                        accessible trough the UI of <strong>RadPivotGrid</strong>. Your customers will be able to filter, sort, modify the descriptions and more through the built-in dropdown menus, dialogs and buttons. The feature can be enabled by simply
                        setting the attached
                        <strong>FieldListBehavior.ShowInline</strong> property as shown below:</p><pre><code>&lt;pivot:RadPivotGrid  x:Name="pivotGrid"  pivot:FieldListBehavior.ShowInline="True"  /&gt;  
</code></pre><p>For more details, make sure to check out the <a href="https://docs.telerik.com/devtools/wpf/controls/radpivotgrid/features/inline-pivotfieldlist" target="_blank">Inline PivotFieldList</a> section from our online
                        help documentation.</p><h3 id="syntaxeditor-word-wrapping">SyntaxEditor: Word Wrapping</h3><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2022/2022-09/syntaxeditor-wordwrap.png?sfvrsn=3f9fdaf1_3" title="Syntax Editor- Word Wrap" alt="SyntaxEditor-WordWrap" /></p><p>A new cool feature for the <strong>SyntaxEditor&nbsp;</strong>is&nbsp;<strong>Word Wrapping</strong>! When the feature is enabled, the horizontal scroll bar is removed and all the text is horizontally fit in the available space. We
                        have also included an additional
                        <a href="https://docs.telerik.com/devtools/wpf/controls/radsyntaxeditor/features/margins" target="_blank">margin</a> that holds the icons and can be removed if needed. I&rsquo;m sure you have seen this view
                        mode in many editors and IDEs, so I hope it will make your WPF applications more useful and user friendly.</p><p>For more info, check out the <a href="https://docs.telerik.com/devtools/wpf/controls/radsyntaxeditor/features/wordwrap" target="_blank">Word Wrap article</a> from the SyntaxEditor help documentation.</p><h3 id="chartview-errorbar-series">ChartView: ErrorBar Series</h3><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2022/2022-09/chart-errorbarseries.png?sfvrsn=6d282099_3" title="Chart-ErrorBarSeries" alt="Chart-ErrorBarSeries" /></p><p>We are adding a new <strong>ChartView</strong> series this release&mdash;<strong>ErrorBar</strong> <strong>Series</strong>! This type of series visualizes its data points using error bar shapes. The error bar shape allows you to
                            display an error or uncertainty in the plotted data. The shape consists of a single line with caps at the two ends. An additional marker that shows the expected measure can be displayed too. </p><p>For more information about all of the setup and customization options of the new series, please check out the <a href="https://docs.telerik.com/devtools/wpf/controls/radchartview/series/cartesianchart-series/bar-series/errorbarseries" target="_blank">ErrorBar Series</a> article from the ChartView help documentation.</p><h3 id="latest-.net-7-preview-support">Latest .NET 7 Preview Support</h3><p>As always, we are up to date with the latest technology trends, and we are happy to announce that Telerik UI for WPF provides support for the latest <a href="https://devblogs.microsoft.com/dotnet/announcing-dotnet-7-preview-7/" target="_blank"><strong>.NET 7 Preview 7</strong></a>. The .NET 7 Preview binaries can be found in a separate zip archive in your account&mdash;download it and give it a try! They will be included in
                            the NuGet packages and in full distribution once .NET 7 becomes official. Also we plan to remove the .NET 5 support with the .NET 7 introduction, so please consider upgrading your .NET 5 applications to newer .NET. (If such
                            a change somehow affects your plans, please contact us and share more details.)</p><h3 id="ribbonview-new-windows11-theme-appearance">RibbonView: New Windows11 Theme Appearance</h3><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2022/2022-09/ribbonview-win11.png?sfvrsn=63911e37_3" title="RibbonView - Win 11" alt="Ribbon View- Win 11" /></p><p>We improved the default <strong>RibbonView</strong> styling for the <strong>Windows 11 theme</strong> in order to resemble the <a href="https://support.microsoft.com/en-us/office/the-new-look-of-office-a6cdf19a-b2bd-4be1-9515-d74a37aa59bf" target="_blank">new Office 365 Experience</a>. Looks nice, doesn&rsquo;t it? </p><p>If you want to see the theme in action, make sure to play around with our <a href="https://demos.telerik.com/wpf/colorthemegenerator/" target="_blank">Color Theme Generator for WPF</a> app! For more details
                            about all the features of the Windows 11 theme, please check out <a href="https://docs.telerik.com/devtools/wpf/styling-and-appearance/themes-suite/windows11" target="_blank">this help article</a>.</p><h3 id="richtextbox-line-numbering">RichTextBox: Line Numbering</h3><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2022/2022-09/rtb-linenumbering.png?sfvrsn=f614404d_3" title="RichTextBox-LineNumbering" alt="RichTextBox-LineNumbering" /></p><p>The latest <strong>RichTextBox</strong> feature enables you to display the appropriate number beside each line of text&mdash;this is useful for specific types of content, such as scripts, legal or medical documents. Through
                                the intuitive API of this feature, you will be able to easily control how the numbering appears. You can change the initial number, the increment number, the distance between the numbering and the document content, and
                                when the numbering should restart. For more information, check out the <a href="https://docs.telerik.com/devtools/wpf/controls/radrichtextbox/features/line-numbering" target="_blank">Line Numbering</a> help article.</p><h3 id="spreadsheet-repeat-specific-rows-or-columns-on-every-printed-page">Spreadsheet: Repeat Specific Rows or Columns on Every Printed Page</h3><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2022/2022-09/spreadsheet-repeatrowscolumns.png?sfvrsn=672d5937_3" title="Spreadsheet-RepeatRowsColumns" alt="Spreadsheet-RepeatRowsColumns" /></p><p>This new <strong>Spreadsheet</strong> functionality allows you to specify a row or a column that will be repeated on every printed page. This functionality is useful when you need to print or export to PDF data spanning multiple
                                pages and still allows the users to see the important information on the top/left side for better orientation. For more details, check out the <a href="https://docs.telerik.com/devtools/wpf/controls/radspreadsheet/features/ui-printing#print-titles" target="_blank">Printing section</a> of our Spreadsheet documentation.</p><h3 id="other-features-1">Other Features</h3><ul><li><strong>SyntaxEditor:</strong> FontWeight and FontStyle of the <a href="https://docs.telerik.com/devtools/wpf/controls/radsyntaxeditor/features/taggers/word-taggers#textformatdefinition" target="_blank">highlighted words</a></li><li><strong>VirtualGrid:</strong> FontWeight and FontStyle of the <a href="https://docs.telerik.com/devtools/wpf/controls/radvirtualgrid/styling-and-appearance/conditional-styling" target="_blank">cells</a></li><li><strong>RibbonWindow:</strong> Windows 11 Theme acrylic effect now can be enabled on all Windows 11 version, not only on the preview ones</li></ul><h3 id="check-out-the-detailed-release-notes-1">Check Out the Detailed Release Notes</h3><p>We have a lot more! To get an overview of all the latest features and improvements we&rsquo;ve made, check out the release notes for the products below:</p><p><a href="https://www.telerik.com/support/whats-new/wpf/release-history" target="_blank">Telerik UI for WPF (Release Notes)</a><br /><a href="https://www.telerik.com/support/whats-new/silverlight/release-history" target="_blank">Telerik UI for Silverlight (Release Notes)</a></p><h3 id="share-your-feedback-1">Share Your Feedback</h3><p>Feel free to drop us a comment below sharing your thoughts. Or visit our Feedback Portals about UI for <a href="https://feedback.telerik.com/wpf" target="_blank">WPF</a>, <a href="https://feedback.telerik.com/silverlight" target="_blank">Silverlight</a> and <a href="https://feedback.telerik.com/document-processing" target="_blank">Document Processing Libraries</a> and let us know if you have
                                any suggestions or if you need any particular features/controls.</p><p>Try out the latest:</p><p><a href="https://www.telerik.com/products/wpf/overview.aspx" class="Btn" target="_blank">Telerik UI for WPF</a>
 <a href="https://www.telerik.com/products/silverlight/overview.aspx" class="Btn" target="_blank">Telerik UI for Silverlight</a></p><p><em>In case you missed it, here are some of the updates from our <a href="https://www.telerik.com/blogs/r2-2022-telerik-desktop-mobile-release#Telerik-UI-for-WPF" target="_blank">last major release</a> and <a href="https://www.telerik.com/blogs/telerik-kendo-ui-june-2022-update#whats-new-in-r2-2022-sp-for-telerik-ui-for-wpf" target="_blank">previous Service Pack</a>.</em></p><h2 id="telerik-ui-for-winforms">What&rsquo;s New in Telerik UI for WinForms With R3 2022</h2><h3 id="spreadsheet-charts">Spreadsheet Charts</h3><p>Hold up? Is that true? Yes, you read it right. Charts are coming to RadSpreadsheet control for Telerik WinForms. What could be a better improvement than visualizing your data beyond the RadSpreadsheet grid? Adding charts
                                    to a workbook can help you identify important statistics and trends in your data that may not be obvious when only looking at numbers. With RadSpreadsheet you can show charts as well as add, remove and manipulate chart
                                    objects in your spreadsheet documents.
                                </p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2022/2022-09/spreadsheet-charts.gif?sfvrsn=5aec3baa_3" title="spreadsheet-charts" alt="spreadsheet-charts" /></p><h3 id="supported-chart-types">Supported Chart Types</h3><p>Different chart types give you the flexibility that your data requires. From Bar to Line, from Point to Bubble, from Pie to Area, show your users that you care. The Spreadsheet component for WinForms supports more than
                                    a dozen different types of charts allowing you to visualize categorical data, numerical data, time series data and more. You can get familiar with all supported types in the <a href="https://docs.telerik.com/devtools/winforms/controls/spreadsheet/features/ui-charts" target="_blank">RadSpreadsheet Charts</a> help article.</p><h3 id="splash-screen">Splash Screen</h3><p>What could be better to notify the end user that something big is loading than showing a splash screen form? Our newest reinforcement to the Telerik UI for the WinForms suite is here. Splash Screen allows you to display
                                    a Telerik themed control that notifies the user that the program is loading. You can customize the image of the splash screen, its animations and loading process visualization per your requirement.</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2022/2022-09/splash-intro.gif?sfvrsn=e6e4c11f_3" title="splash-intro" alt="splash-intro" /></p><h3 id="overlay-and-flyout-screens">Overlay and Flyout Screens</h3><p>If you want something more to sample, just to say &ldquo;give me a second to set up the data,&rdquo; we have just the things for you. Overlay and Flyout Screens will fit perfectly in a case where you want to dim the content
                                    and show the end users to be patient.&nbsp;<span style="background-color:transparent;color:inherit;font-family:inherit;font-size:inherit;text-align:inherit;text-transform:inherit;white-space:inherit;word-spacing:normal;caret-color:auto;"></span><span style="background-color:transparent;color:inherit;font-family:inherit;font-size:inherit;text-align:inherit;text-transform:inherit;white-space:inherit;word-spacing:normal;caret-color:auto;">You could use the Overlay Screen to show only the loading indicator. However, there could be a case where you want to notify the user that he needs to reenter his credentials to continue working on the application.
                                        In this case, Flyout Screen is what you need. The Flyout can be used to display some content over the application or be used as an interactive control. The screen can be customized in a way that you can place input
                                        controls in it, while the Overlay does not accept such customization.</span>
 </p><p><strong>Overlay</strong></p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2022/2022-09/overlay-gif.gif?sfvrsn=82b241dd_3" title="overlay" alt="overlay" /></p><p><strong>Flyout</strong></p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2022/2022-09/flyout-gif.gif?sfvrsn=478352a_3" title="flyout" alt="flyout" /></p><h3 id="changes-to-distribution">Changes to Distribution</h3><p>As of R3 2022 in Telerik UI for WinForms, the .NET 2.0 distribution is removed. From this release, the suite offers .NET 4.8 distribution. With this release, you not only get the .NET Framework projects of the Telerik source
                                    code, but .NET Core projects as well.</p><h3 id="bug-fixes--improvements">Bug Fixes &amp; Improvements</h3><p>Our development team managed to fix/improve more than ONE HUNDRED bugs reported by our customers. We always listen to feedback and try to produce the top-notch controls on the market.</p><p>Share your feedback with us in the <a href="https://feedback.telerik.com/winforms" target="_blank"><strong>Feedback Portal</strong></a>!</p><h3 id="get-the-bits">Get the Bits</h3><p>Don&rsquo;t wait&mdash;try out the latest:</p><p><a href="https://www.telerik.com/winforms" class="Btn" target="_blank">Telerik UI for WinForms</a></p><h2 id="telerik-document-processing-libraries">What&rsquo;s New in Telerik Document Processing Libraries With R3 2022</h2><h3 id="pdfprocessing">PdfProcessing</h3><p><a href="https://docs.telerik.com/devtools/document-processing/libraries/radpdfprocessing/formats-and-conversion/convert-to-image/using-image-format-provider" target="_blank"><strong>Export PDF pages to images</strong></a>:
 We have added the ability to convert the pages of a PDF document to images. This feature uses the <a href="https://docs.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/graphics/skiasharp/" target="_blank">SkiaSharp</a> library. It will work with the .NET Standard version and does not depend on any Windows libraries.</p><h3 id="wordsprocessing">WordsProcessing</h3><p><strong>Page Numbering Fields</strong>: <a href="https://docs.telerik.com/devtools/document-processing/libraries/radwordsprocessing/concepts/fields/page-field" target="_blank">PAGE</a>, <a href="https://docs.telerik.com/devtools/document-processing/libraries/radwordsprocessing/concepts/fields/pageref-field" target="_blank">PAGEREF</a>, <a href="https://docs.telerik.com/devtools/document-processing/libraries/radwordsprocessing/concepts/fields/numpages-fields" target="_blank">NUMPAGES</a>,
 <a href="https://docs.telerik.com/devtools/document-processing/libraries/radwordsprocessing/concepts/fields/sectionpages-field" target="_blank">SECTIONPAGES</a>&nbsp;and <a href="https://docs.telerik.com/devtools/document-processing/libraries/radwordsprocessing/concepts/fields/section" target="_blank">SECTION</a> fields are now supported in our library. These are commonly used fields for inserting page numbering. We have added the ability to update the field values as well.</p><p><a href="https://docs.telerik.com/devtools/document-processing/libraries/radwordsprocessing/model/shapes/shapes" target="_blank"><strong>Shapes support</strong></a>: With this release, we have enabled
                                    users to preserve the shapes when importing and exporting a DOCX document. We will continue working on extending the functionality to allow you to insert and manipulate these objects in the next releases.</p><h3 id="spreadstreamprocessing">SpreadStreamProcessing</h3><p><a href="https://docs.telerik.com/devtools/document-processing/libraries/radspreadstreamprocessing/import" target="_blank"><strong>SpreadStreamProcessing Import</strong></a>: We have added support
                                    for reading XLSX and CSV files. This functionality allows you to easily get the data from large files without loading the entire document in the memory. It has great performance as well.</p><h3 id="spreadprocessing">SpreadProcessing</h3><p><a href="https://docs.telerik.com/devtools/document-processing/libraries/radspreadprocessing/features/worksheetpagesetup#repeating-rowscolumns" target="_blank"><strong>Repeat specific rows or columns on every printed page</strong></a>:
 This feature allows you to specify a row or a column that will be repeated on every printed page.</p><h2 id="telerik-ui-for-net-maui">What&rsquo;s New in Telerik UI for .NET MAUI With R3 2022</h2><p>Aloha, and welcome to another Telerik UI for .NET MAUI release! In addition to the mandatory support for the latest version of .NET MAUI, we are now shipping three brand-new controls as part of our growing Telerik UI for
                                    .NET MAUI suite&mdash;DataForm, AutoComplete and Expander components! We&rsquo;ve also added many enhancements to our powerful DataGrid control. Let&rsquo;s have a sneak peek at the most interesting stuff we have for
                                    you in this release.</p><h3 id="latest-.net-maui--visual-studio-2022-support">Latest .NET MAUI &amp; Visual Studio 2022 Support</h3><p>We follow the Microsoft release cadence closely and have consistently offered early support for all new .NET MAUI versions&mdash;including Day-Zero support when the framework was released in General Availability. Since
                                    then, cross-platform developers have been able to use Telerik UI for .NET MAUI, the most comprehensive cross-platform development UI library on the market, together with the latest .NET MAUI features and fixes: an unbeatable
                                    combination.
                                </p><p>Moreover, with .NET MAUI tooling getting formal support in Visual Studio 2022 17.3, Telerik UI for .NET MAUI is now also tightly integrated with the latest VS version. Developers can also take advantage of dedicated Visual
                                    Studio Extensions with <a href="https://docs.telerik.com/devtools/maui/installation/windows/visualstudio-extensions#using-the-telerik-net-maui-app-project-templates" target="_blank">.NET MAUI templates for project creation</a> and a <a href="https://docs.telerik.com/devtools/maui/installation/windows/toolbox-support" target="_blank">UI Toolbox</a>.</p><h3 id="net-maui-dataform">.NET MAUI DataForm</h3><p>I&rsquo;d like to introduce you to the new <strong>DataForm</strong> control in <strong>Telerik UI for .NET MAUI</strong>. This powerful control helps you to automatically create a form for collecting or editing data. For
                                    example, using the <strong>RadDataForm</strong>, you can easily create form-over-data UI for both mobile and desktop, like these:</p><p><strong>Desktop:</strong></p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2022/2022-09/dataform-firstlook-desktop.png?sfvrsn=a9ff5ddd_3" title=".NET MAUI DataForm" alt=".NET MAUI DataForm" /></p><p><strong>Mobile:</strong></p><p><img sf-custom-thumbnail="true" src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2022/2022-09/dataform-mobile-customization.png?sfvrsn=d45a0616_3" title="dataform-mobile-customization" width="400" alt=".NET MAUI DataForm in mobile layout shows a form with fields for name, username, phone, etc. Each field has an icon, title and helper text" sf-constrain-proportions="true" /></p><p>The component supports different commit modes, allowing you to commit property values one by one or to commit the whole form at once. It&rsquo;s also very easy to add validation to your forms and group UI elements to make
                                    large forms more manageable.</p><p>With the DataForm control, you can not only build the needed UI by using the rich set of editors that are provided out of the box, but you can easily customize those forms through the flexible styling API.</p><p>Here are some of the key features you get in the new DataForm:</p><ul><li><strong>Built-in editors:</strong> The DataForm provides a set of built-in editors for the available primitive types such as numeric, string, boolean, enumerations, DateTime and TimeSpan. The control detects the types
                                        of the data object&rsquo;s properties and automatically displays the appropriate editor.</li><li><strong>Validation support:</strong> You can use the built-in validation support that gives you full control over the data collected through the control.</li><li><strong>Commit modes:</strong> DataForm provides editing support with three types of commit modes to determine when the edited value should be synchronized with the business object.</li><li><strong>Grouping support:</strong> This allows you to easily group the form&rsquo;s editors.</li><li><strong>Data Annotations support:</strong> You can decorate the data models using Data Annotations attributes which specify validation conditions to be applied to a specific field in the DataForm. You can use different
                                        annotations like Requires, DataType, Display, RegularExpression and more.</li><li><strong>Different layouts:</strong> You can arrange the editors and the groups by using different layouts such as stack, grid and more.</li><li><strong>Commands support:</strong> You can execute your validation logic or commit/cancel all pending changes in the form by using the built-in commands for these actions.</li></ul><p>Visit our product documentation for more information on getting started with the <a href="https://docs.telerik.com/devtools/maui/controls/dataform/getting-started" target="_blank">Telerik UI for .NET MAUI DataForm control</a>.</p><h3 id="autocomplete-joins-the-family">AutoComplete Joins the Family</h3><p>The AutoComplete component is a popular control for various mobile and desktop applications and use cases. Especially useful when you have to display a long, predefined list to choose from, such as a list of airports
                                        or a list of known recipients. Your app users expect this in modern apps, and now you can deliver it out of the box.</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2022/2022-09//autocomplete" alt="autocomplete in each Android, iOS, Windows, macOS" title="Autocomplete" /></p><p>Some of the main features of the .NET MAUI AutoComplete are:</p><ul><li><strong>Tokens support:</strong> You can enable the users of your application to search for and select several items from the source of the AutoComplete. These items appear as tokens that can easily be deselected
                                            using their close button.</li><li><strong>Filtering options:</strong> You can define the filtering behavior to display all the matches that either &ldquo;StartsWith&rdquo; or &ldquo;Contains&rdquo; the typed symbols.</li><li><strong>Different suggest modes support:</strong> RadAutoComplete exposes three different modes (Suggest, Append, SuggestAppend) for providing suggestions.</li><li><strong>Placeholder:</strong> This is used to give guidance to the end user on what should be entered in the text input.</li><li><strong>NoResults message:</strong> NoResults message appears in the popup used for the list of suggestions whenever the control cannot find any matching items. Read more about this <a href="https://docs.telerik.com/devtools/maui/controls/autocomplete/configuration#no-results-message" target="_blank">here</a>.</li><li><strong>Visualized text formatting:</strong> You can modify the displayed details of the selected item by using DisplayTextFormatter property of AutoComplete.</li><li><strong>Custom templates:</strong> If any of the default templates do not fit a particular scenario, you can easily define a custom template.</li><li><strong>Highlight customization:</strong> This gives you the ability to highlight the text inside the custom template.</li><li><strong>Nested properties support:</strong> This allows binding of a complex object to the RadAutoComplete&rsquo;s TextSearchPath property.</li></ul><p>Visit our product documentation for more information on getting started with the <a href="https://docs.telerik.com/devtools/maui/controls/autocomplete/overview" target="_blank">Telerik UI for .NET MAUI AutoComplete control</a>.</p><h3 id="net-maui-expander">.NET MAUI Expander</h3><p>RadExpander is a flexible control that helps you save space and achieve easier navigation through your app. You can place the Expander anywhere on your page and embed any content inside the dropdown area. The Expander
                                            control also gives you control over its ExpandDirection to let you adjust the control as per your custom layout.</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2022/2022-09//MAUI_Expander-control-770" alt=".NET MAUI Expander - six cards show small profile pic, name, role (all are sales person) and an amount" title=".NET MAUI Expander" /></p><p>Here are some of the features the Expander control ships with:</p><ul><li><strong>Collapsed and Expanded States:</strong> The control hosts the content in an expandable container that can be easily expanded/collapsed by tapping on its header.</li><li><strong>Animation:</strong> The RadExpander control provides a property that allows you to enable or disable the animation when the content is collapsed/expanded. If you want to enable/disable the animation,
                                                you need to use the IsAnimationEnabled property.</li><li><strong>Customization Options:</strong> The rich API for customization of the Expander component allows you to customize the visual appearance of the control in a variety of ways. You can manipulate the Animation&rsquo;s
                                                duration and easing, the header of the control and its border styles.</li></ul><p>Visit our product documentation for more information on getting started with the <a href="https://docs.telerik.com/devtools/maui/controls/expander/overview" target="_blank">Telerik UI for .NET MAUI Expander control</a>.</p><h3 id="datagrid-just-got-a-new-grouping-ui">DataGrid Just Got a New Grouping UI</h3><p>With our latest release, our powerful DataGrid component has evolved. The new enchantment is the so-called Grouping UI.</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2022/2022-09//MAUI_DataGrid-Grouping-UI-770" alt=".NET MAUI DataGrid Grouping UI - GroupBy Ship Country" title=".NET MAUI DataGrid Grouping UI" /></p><p>This area is called the DataGridServicePanel and allows the user to drag and drop column headers into the panel in order to group the data in the RadDataGrid at runtime.</p><p>The user is not limited to group just a single column&mdash;they are allowed to drag several columns into the panel, or rearrange the grouping. Grouping in this manner gives the user power to control how they
                                                want to view the data and reduces the coding part for the developer.</p><p>If you want to restrict the user from grouping the data or limit the grouping to certain columns, you can do it by using DataGrid&rsquo;s intuitive API for that.</p><p>More information about this feature can be found in <a href="https://docs.telerik.com/devtools/maui/controls/datagrid/overview" target="_blank">DataGrid&rsquo;s product documentation</a>.</p><h3 id="datagrid-footers">DataGrid Footers</h3><p><strong>Column Footers</strong><br />The new addition to the DataGrid control&mdash;the Column Footers functionality&mdash;allows you to display additional information which applies to the columns in a specific
                                                    row placed at the bottom of the control. This row consists of individual footer cells for each column. It is of type object, so you are not limited to just using plain text in it.</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2022/2022-09//MAUI_DataGridColumnFooters-770" alt="DataGrid Column Footers - at the bottom of a grid, there is a footer under the Name column with 'business representative'; 'phone' column has 'business contact', country has 'country'" title="DataGrid Column Footers " data-sf-ec-immutable="
                                                " /></p><p>By default, column footers are hidden, so if you want to make them visible you have to set the DataGrid&rsquo;s <strong>ShowColumnFooters</strong> property to <strong>True</strong>.</p><p>More information about this feature can be found in DataGrid&rsquo;s product documentation.</p><p><strong>Group Footers</strong><br />DataGrid exposes the Group Footers feature, which provides the option to render a footer under each group in the data grid component. Group footers contain footer cells
                                                    that correspond to data columns and can display group summaries.</p><p>This footer row is also hidden by default. If you want to take advantage of this feature, you will have to enable it by setting the <strong>ShowGroupFooters</strong> property of the DataGrid to True.</p><p>More information about this feature can be found in&nbsp;<a href="https://docs.telerik.com/devtools/maui/controls/datagrid/overview" target="_blank" style="background-color:#ffffff;">DataGrid&rsquo;s product documentation</a>.</p><h3 id="datagrid-aggregate-functions ">DataGrid Aggregate Functions</h3><p>There are situations when displaying numbers in the DataGrid in which users would like to be able to see the results from aggregate calculations at the bottom of the DataGrid&rsquo;s groups or columns.
                                                        Now, this can be easily achieved with the new addition to the DataGrid control&mdash;aggregate functions support. It allows you to display aggregated information for the data in the column&rsquo;s
                                                        footer, in the group&rsquo;s header or in the group&rsquo;s footer.<br /></p><p><strong>DataGrid</strong> offers built-in support for the most popular aggregate functions: <strong>Average</strong>, <strong>Count</strong>, <strong>Sum</strong>, <strong>Min</strong>, <strong>Max</strong> and
                                                        <strong>Count.</strong> All you need to do is to add a <strong>PropertyAggregateDescriptors</strong> into DataGrid&rsquo;s <strong>AggregateDescriptors</strong> with the needed function:</p><pre class=" language-xml
                                                "><code class="prism language-xml "><span class="token tag "><span class="token tag "><span class="token punctuation ">&lt;</span><span class="token namespace ">telerikGrid:</span>RadDataGrid</span><span class="token punctuation ">&gt;</span></span>
  <span class="token tag "><span class="token tag "><span class="token punctuation ">&lt;</span><span class="token namespace ">telerikGrid:</span>RadDataGrid.AggregateDescriptors</span><span class="token punctuation ">&gt;</span></span>
    <span class="token tag "><span class="token tag "><span class="token punctuation ">&lt;</span><span class="token namespace ">telerikCore:</span>PropertyAggregateDescriptor</span>  <span class="token attr-name ">PropertyName</span><span class="token
                                                attr-value "><span class="token punctuation ">=</span><span class="token punctuation ">"</span>Points<span class="token punctuation">"</span></span> <span class="token attr-name">Function</span><span class="token attr-value"><span class="token punctuation">=</span>
                                            <span class="token punctuation">"</span>Average<span class="token punctuation">"</span></span><span class="token punctuation">/&gt;</span></span>
                                                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span><span class="token namespace">telerikGrid:</span>RadDataGrid.AggregateDescriptors</span><span class="token punctuation">&gt;</span></span>
                                                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span><span class="token namespace">telerikGrid:</span>RadDataGrid</span><span class="token punctuation">&gt;</span></span>
                                                </code>
                                                        </pre><p>If you have a more complex scenario, you are also covered&mdash;there is an option for creating a custom aggregate function by using a <strong>DelegateAggregateDescriptor</strong>.</p><p>More information about this feature can be found in DataGrid&rsquo;s product documentation.</p><h3 id="sign-up-for-a-trial">Sign Up for a Trial</h3><p>If you&rsquo;re interested in starting to play with .NET MAUI, or if you&rsquo;re already actively working with .NET MAUI to develop applications, I encourage you to check out Telerik UI for .NET
                                                            MAUI.
                                                        </p><p>To get the bits, you just need to sign up for our free 30-day trial, which gives you access to the components as well as our legendary technical support. Head to the <a href="https://www.telerik.com/maui-ui" target="_blank">Telerik UI for .NET MAUI</a> overview page or click the button below and sign up for
                                                            a trial today!</p><p><a href="https://www.telerik.com/try/ui-for-maui" target="_blank" class="Btn">Try Telerik UI For .NET MAUI</a></p><h3 id="share-your-feedback-2">Share Your Feedback</h3><p>Please share your feedback, ideas and suggestions, either by commenting below or by visiting our <a href="https://feedback.telerik.com/maui" target="_blank">Feedback Portal</a> about <a href="https://www.telerik.com/maui-ui" target="_blank">Telerik UI for .NET MAUI</a>. Let us know if
                                                            you have any suggestions and submit your features/controls requests.</p><h2 id="telerik-ui-for-xamarin">What&rsquo;s New in Telerik UI for Xamarin With R3 2022</h2><h3 id="xamarin-datagrid-aggregates">Xamarin DataGrid Aggregates</h3><p>With the new aggregate functions in the Xamarin DataGrid, you can display aggregated information for the data in the group&rsquo;s header, or in the group/column&rsquo;s footer.</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2022/2022-09//Xamarin_DataGrid_AggregateSupport" alt="Xamarin DataGrid Aggregate Support" title="Xamarin DataGrid Aggregate Support" /></p><p>The new feature comes with built-in support for the most popular aggregate functions: <strong>Average</strong>, <strong>Count</strong>, <strong>Sum</strong>, <strong>Min</strong>, <strong>Max</strong> and
                                                            <strong>Count.</strong> You can easily set up the aggregates by adding <strong>PropertyAggregateDescriptors</strong> into DataGrid&rsquo;s <strong>AggregateDescriptors</strong> with the desired
                                                            function:
                                                        </p><pre class=" language-xml"><code class="prism  language-xml"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerikGrid:</span>RadDataGrid</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerikGrid:</span>RadDataGrid.AggregateDescriptors</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token namespace">telerikCore:</span>PropertyAggregateDescriptor</span>  <span class="token attr-name">PropertyName</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Points<span class="token punctuation">"</span></span>  <span class="token attr-name">Function</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Average<span class="token punctuation">"</span></span><span class="token punctuation">/&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span><span class="token namespace">telerikGrid:</span>RadDataGrid.AggregateDescriptors</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span><span class="token namespace">telerikGrid:</span>RadDataGrid</span><span class="token punctuation">&gt;</span></span>
</code></pre><p>The aggregates also support multiple types of complex scenarios through the extensibility point for defining a custom descriptor&mdash;<strong>DelegateAggregateDescriptor</strong>.</p><p>Visit our product documentation for more information on the <a href="https://docs.telerik.com/devtools/xamarin/controls/datagrid/aggregates/overview" target="_blank">Telerik UI for Xamarin Data Grid control and Aggregates</a>.</p><h3 id="xamarin-datagrid-column-footers">Xamarin DataGrid Column Footers</h3><p>The new addition to the DataGrid control&mdash;the Column Footers functionality&mdash;allows you to display additional information which applies to the columns in a specific row placed at the
                                                                bottom of the control. This row consists of individual footer cells for each column. It is of type object, so you are not limited to just using plain text in it.</p><p><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2022/2022-09//Xamarin_DataGrid_Footer-770" alt="Xamarin DataGrid Column Footers - at the bottom of the column for 'sales' the footer reads 'representative name'" title="Xamarin DataGrid Column Footers" /></p><p>By default, column footers are hidden, so if you want to make them visible, you have to set the DataGrid&rsquo;s <strong>ShowColumnFooters</strong> property to <strong>True</strong>.</p><p>Visit our product documentation for more information on the <a href="https://docs.telerik.com/devtools/xamarin/controls/datagrid/columns/columns-footer" target="_blank">Telerik UI for Xamarin Data Grid control and Column Footers</a>.</p><h3 id="xamarin-datagrid-group-footers">Xamarin DataGrid Group Footers</h3><p>With the current release, you have the ability to render a footer under each group inside the DataGrid component. The footer cells correspond to data columns and you can use them to display
                                                                    group summaries.
                                                                </p><p>All you need to do to use this functionality is set the DataGrid.ShowGroupFooters property to true.</p><p>Visit our product documentation for more information on getting started with the <a href="https://docs.telerik.com/devtools/xamarin/controls/datagrid/getting-started" target="_blank">Telerik UI for Xamarin Data Grid control</a>.</p><h3 id="new-islooping-property-now-available-for-all-xamarin-date-and-time-pickers">New IsLooping Property Now Available for All Xamarin Date and Time Pickers</h3><p>With the latest release of Telerik UI for Xamarin, you can easily stop the looping functionality in the Date, Time, DateTime, Time and TimeSpan Pickers using just a single property&mdash;IsLooping.
                                                                    When IsLooping is True, which is by default, the items of each spinner can loop infinitely unless that spinner is restricted to show only a subset of the available values.</p><p><strong>Picker with disabled looping &nbsp;</strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 <strong>Picker with enabled looping</strong><br /><img sf-custom-thumbnail="true" src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2022/2022-09/no-infinite-looping-datepicker.gif?sfvrsn=c82953d4_3" sf-constrain-proportions="true" width="315" alt="" sf-size="175722" />&nbsp;&nbsp;&nbsp;&nbsp;<img sf-custom-thumbnail="true" src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2022/2022-09/picker-islooping.gif?sfvrsn=e816b18f_3" sf-constrain-proportions="true" width="317" alt="" sf-size="216534" /><strong><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2022/2022-09/" alt="" /></strong><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2022/2022-09/" alt="" /></p><p>Visit our product documentation for more information on the <a href="https://docs.telerik.com/devtools/xamarin/controls/datepicker/date-picker-key-features#islooping-property" target="_blank">Telerik UI for Xamarin DatePicker control IsLooping property</a>.</p><h3 id="sign-up-for-a-trial">Get the Latest &amp; Let Us Know Your Feedback</h3><p>Please share your feedback, ideas and suggestions, either by commenting below or by visiting our <a href="https://feedback.telerik.com/xamarin" target="_blank">Feedback Portal</a> about
                                                                    <a href="https://www.telerik.com/xamarin-ui?_ga=2.178034465.587391747.1662994466-1226047811.1616427309" target="_blank">Telerik UI for Xamarin</a>.</p><p>Don&rsquo;t hesitate to check out the latest:</p><p><a href="https://www.telerik.com/xamarin-ui?_ga=2.178034465.587391747.1662994466-1226047811.1616427309" class="Btn" target="_blank">Try Telerik UI For Xamarin</a></p><h2 id="telerik-net-web-desktop-mobile-products-webinar">Telerik .NET Web, Desktop &amp; Mobile Products Webinar &amp; Twitch Session</h2><p><a href="https://www.telerik.com/campaigns/telerik-r3-2022-release-webinar-web-desktop-mobile-products" target="_blank"><img src="https://d585tldpucybw.cloudfront.net/sfimages/default-source/blogs/2022/2022-09/telerik_blog-inline_image_1200x628.png?sfvrsn=9214f6db_3" alt="Telerik .NET Web, Desktop & Mobile Products R3 2022 Webinar" /></a></p><p><strong>Wednesday, September 21, 2022 | 11:00 a.m. &ndash; 1:00 p.m. ET</strong><br />Discover all updates across Telerik UI for Blazor, UI for ASP.NET Core, UI for ASP.NET MVC, UI for ASP.NET
                                                                    AJAX, UI for WPF, UI for WinForms, UI for WinUI, UI for Xamarin and UI for .NET MAUI.</p><p><a href="https://www.telerik.com/campaigns/telerik-r3-2022-release-webinar-web-desktop-mobile-products" class="Btn" target="_blank">Save Your Seat</a></p><h3 id="join-us-on-twitch-today">Join Us on Twitch Today</h3><p><strong>Live from Devreach&rsquo;22 @ Progress360</strong>: Join the <a href="https://twitch.tv/codeitlive" target="_blank"><strong>live community session</strong></a> from the Progress360 Streaming Studio on <strong>September 14 from 10 a.m. &ndash; 11:30 a.m. ET</strong> to hear the release highlights and celebrate the DevReach spirit with us at our
                                                                    Livestream Release Party.</p><h3 id="and-the-best-part-about-the-release-webinars">And the Best Part About the Release Webinars?</h3><p>The live webinars and Twitch sessions are a great opportunity for you to ask questions before and during the webinars. We&rsquo;ll be waiting to hear from you on Twitter&mdash;just use the
                                                                    <strong>#heyTelerik</strong> and <strong>#heyKendoUI</strong> hashtags.
 </p><p>Another great option is the live chat during our release session on <a href="https://www.twitch.tv/codeitlive%22%20/t%20%22_blank" target="_blank"><strong>CodeItLive</strong></a><strong>, our Twitch channel</strong>.</p><img src="https://feeds.telerik.com/link/23072/15640890.gif" height="1" width="1"/>]]></content>
  </entry>
  <entry>
    <id>urn:uuid:f41b849e-1226-4add-ba0d-942ad2307271</id>
    <title type="text">SpreadProcessing: Referencing Whole Columns and Rows Makes Formulas Faster</title>
    <summary type="text">Reference whole columns and rows when working with xlsx files with Telerik SpreadProcessing.</summary>
    <published>2022-08-04T12:58:00Z</published>
    <updated>2026-04-11T21:18:52Z</updated>
    <author>
      <name>Svilen Pavlov </name>
    </author>
    <link rel="alternate" href="https://feeds.telerik.com/link/23072/15543099/spreadprocessing-referencing-whole-columns-rows-makes-formulas-faster"/>
    <category term="Blogs"/>
    <content type="text"><![CDATA[<p><span class="featured">With the latest release, R2 2022, we added support for using references to whole columns and rows for the SpreadProcessing library. Let&rsquo;s take a closer look.</span></p><p>Formulas are one of the most powerful tools that a spreadsheet provides. When referencing the required range for a formula, a specific cell reference often proves less convenient than we would like. This is where this new feature comes in to save the
    day.
</p><p>Suppose we want to sum all numbers in the first row of the following example worksheet:</p><p><img class="WACImage SCXW78114358 BCX0" src="https://www.telerik.comdata:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAhIAAABtCAMAAADDCHiwAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAE1UExURWZmZpycnJ+fn6KioqWlpZqamqioqPDw8Kurq53P///PnWZmnc//////////57aBZmZmgbbn////z51mZue2gf/ntoFmZs//566urmaBtufnz8/nz2adz7adZs+dZp3Pz7GxsYG25+fntrS0tLbn58//z7e3t+f/z7q6ur29vcDAwOf//8PDw8bGxsnJyczMzM/Pz9LS0qenp6qqqqysrLOzs7a2tri4uLu7u8LCwsTExMfHx87OztHR0dPT05mZmdTU1NuQOgAAADqQ22a2/wAAZrb//7ZmAP//25A6AABmtgAAOpDb//+2Zra25///tmYAADqQtv/bkDo6kNv//2Y6kAA6ZmY6AAA6kGYAOjoAOma22zoAZjo6ALb/2zoAADpmtrZmOs/PnefPnba2nbbP/wAAAL4HBb0AAABndFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wAUFrp4AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAIKUlEQVR4Xu2dW3MbRRCF/ZYSiYgcApSCgVIqFA9UyuXyi998gcR2sLEx5pYA4fr//wLTM62VxtpMr/pM1Wh2+1OIvKk6c+k52zNKmtWWYRiGYRiGYRiGYRiGYWwuh/yuxfQYpfUt7PO7FtNjlNa3YHcZRu36Fuwuw6hdfwdymIUUo3Z9zOE995vU5Og9/uEdJPX3H4zH7z/ki3aE/ifb4/GjD/iijZSeuof679BAevy+gcd80Yow/5HTf/gRX7SRnP/HNPTweycO73WwxPTJJ6kFkULqRrOTnJEYUhfP6ad81YYYkp3xZ3zZijh+AWH8YgPp/mn6W5+rbwnfe4dJMM4RHSwxezxLmlwO6fQpYIlRunOHHJK0J8XxC6THLzeQ1MvT7zD/DpMIkCPIEgfh8h1Mnj0UljSpp9EIlkrrv0inKEdK3yUk4vgF0vGTG5DHnwad/wLvCDlLOD84V/BFK+m7zG2l6X0jrZ9+KVoCvUvE8aePMkL8fAPq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" style="margin:0px;padding:0px;user-select:text;-webkit-user-drag:none;-webkit-tap-highlight-color:transparent;border-width:initial;border-style:none;vertical-align:baseline;white-space:pre !important;" width="530" height="108" alt="In a spreadsheet, the top row increments from A to H so A=1 and H=8" /></p><p>As you can see, the first row contains numbers up to column H. We could use a standard cell reference in the formulas such as =SUM(A1:H1). Although this would work for the time being, the worksheet&rsquo;s data might undergo changes in the future, which
    could affect the formula and render it erroneous.&nbsp;<br /><br />With the addition of the whole column/row references, we can easily bypass such potential issues. Here is how the above formula would look using a whole row reference: =SUM(1:1). You
    can set a cell&rsquo;s value using the newly supported references just as you would using the cell references. In the below code, we create a new workbook, add a new worksheet to it, and then set the value of cell B1 to the above formula:&nbsp;</p><pre><code class="language-csharp">Workbook workbook = new Workbook(); 

Worksheet worksheet = workbook.Worksheets.Add(); 
worksheet.Cells[1,0].SetValue("=SUM(1:1)"); </code></pre><p><span style="background-color:transparent;color:inherit;font-family:inherit;font-size:inherit;text-align:inherit;text-transform:inherit;white-space:inherit;word-spacing:normal;caret-color:auto;--darkreader-inline-bgcolor:transparent;--darkreader-inline-color:inherit;" data-darkreader-inline-bgcolor="" data-darkreader-inline-color="">The same applies to columns. Alongside referencing specific cells, you can now use entire column references. In the worksheet above, the formula =SUM(A1:D3), would return the same result as =SUM(A:D).&nbsp;</span></p><h2>Retaining High Performance</h2><p>Referencing entire rows and columns could mean including thousands or even millions of cells in a cell range, which could impact a worksheet&rsquo;s performance. Therefore, our team has taken care to maintain the library&rsquo;s high efficiency when implementing
    the feature. Not sure? Try it yourself and be pleasantly surprised with how blazingly fast formulas evaluate.</p><h2>Practical Application</h2><p>When introducing a new tool, it is always easier to understand when and how to use it by sharing a practical use case scenario where it comes in handy. Since our team recently implemented one of the most requested features, Conditional Formatting, we
    can use it as a context for showing off some benefits of referencing entire rows and columns. Conditional Formatting helps us analyze data visually by configuring a set of formatting rules to be applied over a specified range.</p><p>In the code below, we create a small table in an existing Worksheet, then append a row on its right, which shows the average for each column. Instead of referencing the beginning and end cells of each column in the formula used, we can easily reference
    the entire columns:</p><pre><code class="language-csharp">var tableSize = 5;
for (int row = 0; row &lt; tableSize; row++)
{
    for (int col = 0; col &lt; tableSize; col++)
    {
        worksheet.Cells[row, col].SetValue(row + col);
    }
}
char asciiColSymbol = 'A';
for (int row = 0; row &lt; tableSize ; row++)
{
    string headerColumnText = string.Format("Average {0}:", asciiColSymbol);
    worksheet.Cells[row, tableSize].SetValue(headerColumnText);
    string formula = string.Format("=AVERAGE({0}:{1})", asciiColSymbol, asciiColSymbol);
    worksheet.Cells[row, tableSize+1].SetValue(formula);

    asciiColSymbol++;
}

DataBarValueContext dataBarValueContext = new DataBarValueContext();
DataBarRule dataBarRule = new DataBarRule(dataBarValueContext);
dataBarRule.FillColor = new ThemableColor(Colors.Aqua);
ConditionalFormatting conditionalFormatting = new ConditionalFormatting(dataBarRule);

var averageColumn=tableSize+1;
worksheet.Cells[0, averageColumn, averageColumn, averageColumn].AddConditionalFormatting(conditionalFormatting);
</code></pre><p>Here we can see the exported worksheet with the column averages: </p><p><img src="https://www.telerik.comdata:image/png;base64,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" alt="A spreadsheet has incrementing columns and rows, such that A1=0 and E5=8; then column F has titles Average A through E; and column G shows the numbers of the averages 2 up to 6, and a bar that grows in each incrementing cell" /></p><p>Don&rsquo;t forget to check out our new Conditional Formatting feature in more detail in the <a href="https://www.telerik.com/blogs/make-data-easy-analyze-conditional-formatting-spreadprocessing" target="_blank">Conditional Formatting blog article</a>.</p><h2>Share Your Feedback</h2><p>If you have yet to try Telerik Document Processing, you can <a href="https://www.telerik.com/download-trial-file/v2-b/devcraft-ultimate" target="_blank">download a free trial</a> and check out the fantastic features the libraries
    support.</p><p>If you are already using the libraries, we are always eager to receive your feedback. Don&rsquo;t be shy and drop us a comment with your thoughts or visit <a href="https://feedback.telerik.com/document-processing" target="_blank">our Document Processing Libraries Feedback Portal</a> and let us know if you have any suggestions or need any specific functionality implemented.</p><img src="https://feeds.telerik.com/link/23072/15543099.gif" height="1" width="1"/>]]></content>
  </entry>
</feed>
