Example T889870
Visible to All Users

Web Rich Text Editor - How to integrate a control into an MVC application

This example is a ready-to-use MVC application with the DevExpress RichEdit component.

Requirements

  • To use the RichEdit control in an ASP.NET MVC application, you need to have a Universal, DXperience, or ASP.NET subscription.
  • Versions of the devexpress npm packages should be identical (their major and minor versions should be the same).

This example illustrates a possible way of integrating the client Rich Text Editor into an MVC application using steps from the following help topic: Rich Text Editor > Get Started > MVC Application.

Files to Look At

Documentation

More Examples

Example Code

RichMVC/Views/Home/Index.cshtml
Razor
@{ ViewBag.Title = "Home Page"; } @Scripts.Render("~/Scripts/creator.js") <button onclick="setDataSource(window.rich, '@Url.Action("GetDataSource", "Home", null, Request.Url.Scheme)')">setDataSource</button> <button onclick="appendMergeFields(window.rich)">addMergeFields</button> <button onclick="mailMerge(window.rich)">mailMerge</button> <div id='rich-container' style="width: 100%; height: 900px"></div> <script> $(document).ready(function () { const rich = createRichEdit($("#rich-container"), { exportUrl: '@Url.Action("ExportDocument", "Home", null, Request.Url.Scheme)', document: "@ViewBag.Document", }); window.rich = rich; }); </script>
RichMVCVB/Views/Home/Index.vbhtml
Code
@Code ViewData("Title") = "Home Page" End Code @Scripts.Render("~/Scripts/creator.js") <button onclick="setDataSource(window.rich, '@Url.Action("GetDataSource", "Home", Nothing, Request.Url.Scheme)')">setDataSource</button> <button onclick="appendMergeFields(window.rich)">addMergeFields</button> <button onclick="mailMerge(window.rich)">mailMerge</button> <div id='rich-container' style="width: 100%; height: 900px"></div> <script> $(document).ready(function () { const rich = createRichEdit($("#rich-container"), { exportUrl: '@Url.Action("ExportDocument", "Home", Nothing, Request.Url.Scheme)', document: "@ViewBag.Document", }); window.rich = rich; }); </script>
RichMVC/Views/Shared/_Layout.cshtml
Razor
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>@ViewBag.Title</title> @Styles.Render("~/node_modules/devextreme/dist/css/dx.common.css") @Styles.Render("~/node_modules/devextreme/dist/css/dx.light.compact.css") @Styles.Render("~/node_modules/devexpress-richedit/dist/dx.richedit.css") @Scripts.Render("~/node_modules/devexpress-richedit/dist/custom/dx.richedit.min.js") @Html.DevExpress().GetStyleSheets( new StyleSheet { ExtensionSuite = ExtensionSuite.NavigationAndLayout }, new StyleSheet { ExtensionSuite = ExtensionSuite.Editors } ) @Html.DevExpress().GetScripts( new Script { ExtensionSuite = ExtensionSuite.NavigationAndLayout }, new Script { ExtensionSuite = ExtensionSuite.Editors } ) </head> <body> @RenderBody() </body> </html>
RichMVCVB/Views/Shared/_Layout.vbhtml
Code
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>@ViewData("Title")</title> @Styles.Render("~/node_modules/devextreme/dist/css/dx.common.css") @Styles.Render("~/node_modules/devextreme/dist/css/dx.light.compact.css") @Styles.Render("~/node_modules/devexpress-richedit/dist/dx.richedit.css") @Scripts.Render("~/node_modules/devexpress-richedit/dist/custom/dx.richedit.min.js") @Html.DevExpress().GetStyleSheets(New StyleSheet With {.ExtensionSuite = ExtensionSuite.NavigationAndLayout}, New StyleSheet With {.ExtensionSuite = ExtensionSuite.Editors}) @Html.DevExpress().GetScripts(New Script With {.ExtensionSuite = ExtensionSuite.NavigationAndLayout}, New Script With {.ExtensionSuite = ExtensionSuite.Editors}) </head> <body> @RenderBody() </body> </html>
RichMVC/Scripts/creator.js
JavaScript
/// <reference path="../node_modules/devexpress-richedit/dist/dx.richedit.d.ts" /> function createRichEdit(richEditContainer, initialOptions) { /** @type {DevExpress.RichEdit.Options} */ var options = DevExpress.RichEdit.createOptions(); customizeRibbon(options); options.exportUrl = initialOptions.exportUrl; options.confirmOnLosingChanges.enabled = false; var elem = document.createElement('div'); richEditContainer.append(elem); /** @type {DevExpress.RichEdit.RichEdit} */ var rich = DevExpress.RichEdit.create(elem, options); rich.openDocument(initialOptions.document, 'fileName', DevExpress.RichEdit.DocumentFormat.OpenXml, function () { rich.document.insertText(rich.document.length, 'Some text'); }); return rich; } /** * @param {DevExpress.RichEdit.Options} options */ function customizeRibbon(options) { options.ribbon.removeTab(DevExpress.RichEdit.RibbonTabType.MailMerge); options.ribbon.removeTab(DevExpress.RichEdit.RibbonTabType.References); options.ribbon.getTab(DevExpress.RichEdit.RibbonTabType.File) .removeItem(DevExpress.RichEdit.FileTabItemId.OpenDocument); options.ribbon.getTab(DevExpress.RichEdit.RibbonTabType.View) .removeItem(DevExpress.RichEdit.ViewTabItemId.ToggleShowHorizontalRuler); } /** * @param {DevExpress.RichEdit.RichEdit} rich * @param {string} url */ function setDataSource(rich, url) { rich.loadingPanel.show(); $.get(url, function (data) { rich.mailMergeOptions.setDataSource(data, function () { rich.loadingPanel.hide(); }); }, "json"); } /** * @param {DevExpress.RichEdit.RichEdit} rich */ function mailMerge(rich) { if (!rich.mailMergeOptions.getDataSource()) { alert('No data source'); return; } rich.loadingPanel.show(); rich.mailMerge(function (documentAsBlob) { blobToBase64(documentAsBlob, function (documentAsBase64) { rich.openDocument(documentAsBase64, 'MergedDocument', DevExpress.RichEdit.DocumentFormat.OpenXml, function () { rich.loadingPanel.hide(); }); }); }, DevExpress.RichEdit.MergeMode.NewParagraph, DevExpress.RichEdit.DocumentFormat.OpenXml); } function blobToBase64(blob, callback) { var reader = new FileReader(); reader.readAsDataURL(blob); reader.onloadend = function () { var base64data = reader.result; callback(base64data); } } /** * @param {DevExpress.RichEdit.RichEdit} rich */ function appendMergeFields(rich) { var position = rich.selection.active; var sd = rich.selection.activeSubDocument; function insertField(name) { var field = sd.fields.createMergeField(position, name); field.update(); position = field.interval.end; } rich.beginUpdate(); rich.history.beginTransaction(); position = sd.insertParagraph(position).interval.end; position = sd.insertText(position, 'FirstName: ').end; insertField('FirstName'); position = sd.insertText(position, ', Id: ').end; insertField('Id'); position = sd.insertParagraph(position).interval.end; rich.history.endTransaction(); rich.endUpdate(); rich.focus(); }
RichMVC/Controllers/HomeController.cs
C#
using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace RichMVC.Controllers { public class HomeController : Controller { private const string documentFolderPath = "~/Docs/"; public ActionResult Index() { ViewBag.Document = Convert.ToBase64String(System.IO.File.ReadAllBytes(Server.MapPath($"{documentFolderPath}template.docx"))); return View(); } [HttpPost] public ActionResult ExportDocument(string base64, string fileName, int format, string reason) { byte[] fileContent = Convert.FromBase64String(base64); System.IO.File.WriteAllBytes(Server.MapPath($"{documentFolderPath}{fileName}.{GetExtension(format)}"), fileContent); return new EmptyResult(); } [HttpGet] public JsonResult GetDataSource() { int id = 0; var jsondata = new[] { "John", "Piter", "Mark" }.Select(name => new Hashtable() { { "FirstName", name }, { "Id", id++ } }).ToList(); return Json(jsondata, JsonRequestBehavior.AllowGet); } private static string GetExtension(int format) { switch (format) { case 4: return "docx"; case 2: return "rtf"; case 1: return "txt"; } return "docx"; } } }
RichMVCVB/Controllers/HomeController.vb
Visual Basic
Public Class HomeController Inherits System.Web.Mvc.Controller Private Const documentFolderPath = "~/Docs/" Function Index() As ActionResult ViewBag.Document = Convert.ToBase64String(System.IO.File.ReadAllBytes(Server.MapPath($"{documentFolderPath}template.docx"))) Return View() End Function <HttpPost> Public Function ExportDocument(ByVal base64 As String, ByVal fileName As String, ByVal format As Integer, ByVal reason As String) As ActionResult Dim fileContent As Byte() = Convert.FromBase64String(base64) System.IO.File.WriteAllBytes(Server.MapPath($"{documentFolderPath}{fileName}.{GetExtension(format)}"), fileContent) Return New EmptyResult() End Function Private Shared Function GetExtension(ByVal format As Integer) As String Select Case format Case 4 Return "docx" Case 3 Return "rtf" Case 1 Return "txt" End Select Return "docx" End Function <HttpGet> Public Function GetDataSource() As JsonResult Dim id As Integer = 0 Dim jsondata = {"John", "Piter", "Mark"}.[Select](Function(name) New Hashtable() From { {"FirstName", name}, {"Id", Math.Min(System.Threading.Interlocked.Increment(id), id - 1)} }).ToList() Return Json(jsondata, JsonRequestBehavior.AllowGet) End Function End Class

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.