Example T1251646
Visible to All Users

Rich Text Editor and HTML Editor for Blazor - How to integrate AI-powered extensions

This example enables AI-powered extensions for both the DevExpress Blazor Rich Text Editor and HTML Editor. These extensions supply AI functions designed to process text/HTML content.

Implementation Details

Both the DevExpress Blazor Rich Text Editor (DxRichEdit) and Blazor HTML Editor (DxHtmlEditor) ship with an AdditionalItems property. You can populate this property with commands and allow users to process editor text as needs dictate. Available commands for both editors are as follows:

  • Ask AI Assistant allows user to process text based on a custom prompt.
  • Change Style rewrite text using a specified style.
  • Change Tone rewrite text using a specified tone.
  • Describe Picture generates the description for an image (for Rich Text Editor only).
  • Expand expands text.
  • Explain explains text.
  • Proofread proofreads text.
  • Shorten shortens text.
  • Summarize summarizes text.
  • Translate translates text into the specified language.

Register AI Services

[!NOTE]
DevExpress AI-powered extensions follow the "bring your own key" principle. DevExpress does not offer a REST API and does not ship any built-in LLMs/SLMs. You need an active Azure/Open AI subscription to obtain the REST API endpoint, key, and model deployment name. These variables must be specified at application startup to register AI clients and enable DevExpress AI-powered Extensions in your application.

Add the following code to the Program.cs file to register AI services in the application:

C#
using Azure; using Azure.AI.OpenAI; using Microsoft.Extensions.AI; ... string azureOpenAIEndpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT"); string azureOpenAIKey = Environment.GetEnvironmentVariable("AZURE_OPENAI_API_KEY"); string deploymentName = string.Empty; IChatClient chatClient = new AzureOpenAIClient( new Uri(azureOpenAIEndpoint), new AzureKeyCredential(azureOpenAIKey)).AsChatClient(deploymentName); builder.Services.AddDevExpressBlazor(); builder.Services.AddChatClient(config => config.Use(chatClient)); builder.Services.AddDevExpressAI();

Enable AI-powered extension for the DevExpress Blazor Rich Text Editor

AI-powered extension for our Blazor Rich Text Editor adds AI-related commands to the editor's context menu.

You can add predefined commands or implement custom commands as necessary. This example introduces a Rewrite like Shakespeare context menu item.

C#
public class ShakespeareAIContextMenuItem : BaseAIContextMenuItem { [Inject] IAIExtensionsContainer? aIExtensionsContainer { get; set; } protected override string DefaultItemText => "Rewrite like Shakespeare"; protected override Task<TextResponse> GetCommandTextResult(string text) { var customExtension = aIExtensionsContainer.CreateCustomPromptExtension(); return customExtension.ExecuteAsync(new CustomPromptRequest("Rewrite the following text in William Shakespeare style.", text)); } }

Declare DxRichEdit's AdditionalItems and populate it with commands in the following manner:

Razor
@using DevExpress.AIIntegration.Blazor.RichEdit @using DevExpress.Blazor.RichEdit <DxRichEdit DocumentContent="DocumentContent" CssClass="my-editor"> <AdditionalItems> <ShakespeareAIContextMenuItem /> <SummarizeAIContextMenuItem /> <ExplainAIContextMenuItem /> <ProofreadAIContextMenuItem /> <ExpandAIContextMenuItem /> <ShortenAIContextMenuItem /> <AskAssistantAIContextMenuItem /> <ChangeStyleAIContextMenuItem /> <ChangeToneAIContextMenuItem /> <TranslateAIContextMenuItem Languages="@("German, French, Chinese")" /> </AdditionalItems> </DxRichEdit>

Enable AI-powered extension for the DevExpress Blazor HTML Editor

The AI-powered extension for our Blazor HTML Editor adds AI-related commands to the editor's toolbar.

You can add predefined commands or implement custom commands as necessary. This example introduces a Rewrite like Shakespeare toolbar item.

C#
public class ShakespeareAIToolbarItem: BaseAIToolbarItem { [Inject] IAIExtensionsContainer? aIExtensionsContainer { get; set; } protected override string DefaultItemText => "Rewrite like Shakespeare"; protected override Task<TextResponse> GetCommandTextResult(string text) { var customExtension = aIExtensionsContainer.CreateCustomPromptExtension(); return customExtension.ExecuteAsync(new CustomPromptRequest("Rewrite the following text in William Shakespeare style.", text)); } }

Declare DxHtmlEditor's AdditionalItems and populate it with commands in the following manner:

Razor
@using DevExpress.AI.Samples.Blazor.Editors.Components.AdditionalItems @using DevExpress.AIIntegration.Blazor.HtmlEditor <DxHtmlEditor @bind-Markup="Value" CssClass="my-editor" BindMarkupMode="HtmlEditorBindMarkupMode.OnLostFocus"> <AdditionalItems> <ShakespeareAIToolbarItem /> <SummarizeAIToolbarItem /> <ExplainAIToolbarItem /> <ProofreadAIToolbarItem /> <ExpandAIToolbarItem /> <ShortenAIToolbarItem /> <AskAssistantAIToolbarItem /> <ChangeStyleAIToolbarItem /> <ChangeToneAIToolbarItem /> <TranslateAIToolbarItem Languages="@("German, French, Chinese")" /> </AdditionalItems> </DxHtmlEditor>

Files to Review

Documentation

Online Demo

More Examples

Does this example address your development requirements/objectives?

(you will be redirected to DevExpress.com to submit your response)

Example Code

DevExpress.AI.Samples.Blazor.Editors/Components/Pages/RichEdit.razor
Razor
@page "/" @using DevExpress.AIIntegration.Blazor.RichEdit @using DevExpress.AI.Samples.Blazor.Editors.Components.AdditionalItems @using DevExpress.Blazor.RichEdit @using System.Reflection <DxRichEdit DocumentContent="DocumentContent" CssClass="my-editor"> <AdditionalItems> <ShakespeareAIContextMenuItem /> <SummarizeAIContextMenuItem /> <ExplainAIContextMenuItem /> <ProofreadAIContextMenuItem /> <ExpandAIContextMenuItem /> <ShortenAIContextMenuItem /> <AskAssistantAIContextMenuItem /> <ChangeStyleAIContextMenuItem /> <ChangeToneAIContextMenuItem /> <TranslateAIContextMenuItem Languages="@("German, French, Chinese")" /> </AdditionalItems> </DxRichEdit> @code { const string DocumentResourceName = "DevExpress.AI.Samples.Blazor.Editors.Docs.Example.docx"; byte[] DocumentContent { get; set; } protected override void OnInitialized() { using (var ms = new MemoryStream()) { var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(DocumentResourceName); stream?.CopyTo(ms); DocumentContent = ms.ToArray(); } base.OnInitialized(); } }
DevExpress.AI.Samples.Blazor.Editors/Components/Pages/HtmlEditor.razor
Razor
@page "/htmleditor" @using DevExpress.AI.Samples.Blazor.Editors.Components.AdditionalItems @using DevExpress.AIIntegration.Blazor.HtmlEditor <DxHtmlEditor @bind-Markup="Value" CssClass="my-editor" BindMarkupMode="HtmlEditorBindMarkupMode.OnLostFocus"> <AdditionalItems> <ShakespeareAIToolbarItem /> <SummarizeAIToolbarItem /> <ExplainAIToolbarItem /> <ProofreadAIToolbarItem /> <ExpandAIToolbarItem /> <ShortenAIToolbarItem /> <AskAssistantAIToolbarItem /> <ChangeStyleAIToolbarItem /> <ChangeToneAIToolbarItem /> <TranslateAIToolbarItem Languages="@("German, French, Chinese")" /> </AdditionalItems> </DxHtmlEditor> @code { public string Value { get; set; } = @"<h2> HTML Editor </h2><br> <p>The HTML Editor component for Blazor is a WYSIWYG (what you see is what you get) text editor that allows users to format text and add graphics. The document can use HTML or Markdown format.</p> <p>Supported features:</p> <ul> <li>Inline formats: <ul> <li><strong>Bold</strong>, <em>italic</em>, <s>strikethrough</s> text formatting</li> <li>Font, size, color changes (HTML only)</li> </ul> </li> <li>Block formats: <ul> <li>Headings</li> <li>Text alignment</li> <li>Lists (bullet and numbered)</li> <li>Code blocks</li> <li>Quotes</li> </ul> </li> <li>HTML and Markdown support</li> <li>Variable support: produce documents based on templates</li> <li>Toolbar with adaptive layout support</li> <li>Insert images: specify a URL or upload from the local file system</li> <li>Table support</li> </ul> <p>Supported browsers: <table> <tbody> <tr> <td><strong>Google Chrome (including Android)</strong></td> <td>Latest</td> </tr> <tr> <td><strong>Apple Safari (including iOS)</strong></td> <td>Latest</td> </tr> <tr> <td><strong>Mozilla Firefox</strong></td> <td>Latest</td> </tr> <tr> <td><strong>Microsoft Edge</strong></td> <td>Latest</td> </tr> <tr> <td><strong><a href='https://support.microsoft.com/en-us/microsoft-edge/what-is-microsoft-edge-legacy-3e779e55-4c55-08e6-ecc8-2333768c0fb0' rel='noopener noreferrer' target='_blank'>Microsoft Edge Legacy</a></strong></td> <td>Not supported</td> </tr> </tbody> </table> <br>"; }
DevExpress.AI.Samples.Blazor.Editors/Components/AdditionalItems/ShakespeareAIContextMenuItem.cs
C#
using DevExpress.AIIntegration; using DevExpress.AIIntegration.Blazor.RichEdit; using DevExpress.AIIntegration.Extensions; using Microsoft.AspNetCore.Components; namespace DevExpress.AI.Samples.Blazor.Editors.Components.AdditionalItems { public class ShakespeareAIContextMenuItem : BaseAIContextMenuItem { [Inject] IAIExtensionsContainer? aIExtensionsContainer { get; set; } protected override string DefaultItemText => "Rewrite like Shakespeare"; protected override Task<TextResponse> GetCommandTextResult(string text) { var customExtension = aIExtensionsContainer.CreateCustomPromptExtension(); return customExtension.ExecuteAsync(new CustomPromptRequest("Rewrite the following text in William Shakespeare style.", text)); } } }
DevExpress.AI.Samples.Blazor.Editors/Components/AdditionalItems/ShakespeareAIToolbarItem.cs
C#
using DevExpress.AIIntegration; using DevExpress.AIIntegration.Blazor.HtmlEditor; using DevExpress.AIIntegration.Extensions; using Microsoft.AspNetCore.Components; namespace DevExpress.AI.Samples.Blazor.Editors.Components.AdditionalItems { public class ShakespeareAIToolbarItem: BaseAIToolbarItem { [Inject] IAIExtensionsContainer? aIExtensionsContainer { get; set; } protected override string DefaultItemText => "Rewrite like Shakespeare"; protected override Task<TextResponse> GetCommandTextResult(string text) { var customExtension = aIExtensionsContainer.CreateCustomPromptExtension(); return customExtension.ExecuteAsync(new CustomPromptRequest("Rewrite the following text in William Shakespeare style.", text)); } } }
DevExpress.AI.Samples.Blazor.Editors/Program.cs
C#
using Azure; using Azure.AI.OpenAI; using DevExpress.AI.Samples.Blazor.Editors.Components; using Microsoft.Extensions.AI; var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddRazorComponents() .AddInteractiveServerComponents(); string azureOpenAIEndpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT"); string azureOpenAIKey = Environment.GetEnvironmentVariable("AZURE_OPENAI_API_KEY"); string deploymentName = string.Empty; IChatClient chatClient = new AzureOpenAIClient( new Uri(azureOpenAIEndpoint), new AzureKeyCredential(azureOpenAIKey)).AsChatClient(deploymentName); builder.Services.AddDevExpressBlazor(); builder.Services.AddChatClient(config => config.Use(chatClient)); builder.Services.AddDevExpressAI(); var app = builder.Build(); // Configure the HTTP request pipeline. if(!app.Environment.IsDevelopment()) { app.UseExceptionHandler("/Error", createScopeForErrors: true); // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseAntiforgery(); app.MapRazorComponents<App>() .AddInteractiveServerRenderMode(); app.Run();

Disclaimer: The information provided on DevExpress.com and affiliated web properties (including the DevExpress Support Center) is provided "as is" without warranty of any kind. Developer Express Inc disclaims all warranties, either express or implied, including the warranties of merchantability and fitness for a particular purpose. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.

Confidential Information: Developer Express Inc does not wish to receive, will not act to procure, nor will it solicit, confidential or proprietary materials and information from you through the DevExpress Support Center or its web properties. Any and all materials or information divulged during chats, email communications, online discussions, Support Center tickets, or made available to Developer Express Inc in any manner will be deemed NOT to be confidential by Developer Express Inc. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.