Example T917398
Visible to All Users

Rich Text Editor for ASP.NET Core - How to load/save documents from/to a database

This example demonstrates how to configure the Rich Text Editor control to load/save documents from/to a database.

Rich Text Editor

Overview

Follow the steps bellow to configure the Rich Text Editor to work with a database:

  1. Create a class that models a document. This class should be able to store document identifiers, file formats, and content:
    C#
    public class DocumentInfo { [Key] public int ID { set; get; } [Column("documentName")] public string DocumentName { set; get; } [Column("documentBytes")] public byte[] DocumentBytes { set; get; } [Column("documentFormat")] public int DocumentFormat { set; get; } }
  2. Register the database context and add a connection string.
  3. In the Index action method, load a document from the database and save the document to a model:
    C#
    public IActionResult Index() { var model = _context.Docs.FirstOrDefault(); if (model == null) model = new DocumentInfo(); return View(model); }
  4. Create the Rich Text Editor and call its Open method to open the document stored in the model:
    Razor
    @(Html.DevExpress().RichEdit("richEdit") .Width("100%") .Height(800) .ExportUrl(Url.Action("SaveDocument")) .Open(() => { return Model.DocumentBytes; }, (DevExpress.AspNetCore.RichEdit.DocumentFormat)Model.DocumentFormat) )
  5. Implement an action method that saves the document opened in the Rich Text Editor control back to the database. Assign this action method to the control's ExportUrl property:
    C#
    public IActionResult SaveDocument(string base64, string fileName, int format, string reason) { byte[] fileContents = System.Convert.FromBase64String(base64); var doc = _context.Docs.FirstOrDefault(); if (doc == null) { doc = new DocumentInfo(); doc.DocumentBytes = fileContents; doc.DocumentFormat = format; doc.DocumentName = fileName; _context.Docs.Add(doc); } else { doc.DocumentBytes = fileContents; doc.DocumentFormat = format; doc.DocumentName = fileName; } _context.SaveChanges(); return Ok(); }

Files to Review

Documentation

More Examples

Does this example address your development requirements/objectives?

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

Example Code

Views/Home/Index.cshtml
Razor
@{ ViewData["Title"] = "Home Page"; } @model RichSaveLoadDB.Models.DocumentInfo <script src="~/node_modules/jszip/dist/jszip.min.js"></script> <script src="~/node_modules/devextreme-dist/js/dx.all.js"></script> <link href="~/node_modules/devextreme-dist/css/dx.common.css" rel="stylesheet" /> <link href="~/node_modules/devextreme-dist/css/dx.light.css" rel="stylesheet" /> @* If you export a document to PDF on the client side (the exportToPdf method) or enable client PDF printing mode, you should register the pdfkit library before control script registration.*@ <script src="~/node_modules/devexpress-richedit/dist/pdfkit.js"></script> <script src="~/node_modules/devexpress-richedit/dist/dx.richedit.js"></script> <link href="~/node_modules/devexpress-richedit/dist/dx.richedit.css" rel="stylesheet" /> @(Html.DevExpress().RichEdit("richEdit") .Width("100%") .Height(800) .ExportUrl(Url.Action("SaveDocument")) .Open(() => { return Model.DocumentBytes; }, (DevExpress.AspNetCore.RichEdit.DocumentFormat)Model.DocumentFormat) )
Controllers/HomeController.cs
C#
using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using RichSaveLoadDB.Models; namespace RichSaveLoadDB.Controllers { public class HomeController : Controller { private readonly DocsDbContext _context; public HomeController(DocsDbContext context) { _context = context; _context.Database.EnsureCreated(); } public IActionResult Index() { var model = _context.Docs.FirstOrDefault(); if (model == null) model = new DocumentInfo(); return View(model); } public IActionResult Privacy() { return View(); } [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] public IActionResult Error() { return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier }); } public IActionResult SaveDocument(string base64, string fileName, int format, string reason) { byte[] fileContents = System.Convert.FromBase64String(base64); var doc = _context.Docs.FirstOrDefault(); if (doc == null) { doc = new DocumentInfo(); doc.DocumentBytes = fileContents; doc.DocumentFormat = format; doc.DocumentName = fileName; _context.Docs.Add(doc); } else { doc.DocumentBytes = fileContents; doc.DocumentFormat = format; doc.DocumentName = fileName; } _context.SaveChanges(); return Ok(); } } }
Models/DocumentInfo.cs
C#
using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using System.Linq; using System.Threading.Tasks; namespace RichSaveLoadDB.Models { public class DocumentInfo { [Key] public int ID { set; get; } [Column("documentName")] public string DocumentName { set; get; } [Column("documentBytes")] public byte[] DocumentBytes { set; get; } [Column("documentFormat")] public int DocumentFormat { set; get; } } }
Models/DocsDbContext.cs
C#
using Microsoft.EntityFrameworkCore; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace RichSaveLoadDB.Models { public class DocsDbContext : DbContext { public DocsDbContext(DbContextOptions<DocsDbContext> options) : base(options) { } public DbSet<DocumentInfo> Docs { get; set; } } }
Startup.cs
C#
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.HttpsPolicy; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.FileProviders; using Microsoft.Extensions.Hosting; using RichSaveLoadDB.Models; namespace RichSaveLoadDB { public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddControllersWithViews(); services.AddMvc().AddRazorPagesOptions(o => { o.Conventions.ConfigureFilter(new IgnoreAntiforgeryTokenAttribute()); }); services.AddDbContext<DocsDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DocsDbContext")) ); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Home/Error"); // 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.UseStaticFiles(new StaticFileOptions { FileProvider = new PhysicalFileProvider(Path.Combine(env.ContentRootPath, "node_modules")), RequestPath = "/node_modules" }); app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); }); } } }
appsettings.json
JSON
{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information" } }, "AllowedHosts": "*", "ConnectionStrings": { "DocsDbContext": "Server=(localdb)\\mssqllocaldb;Database=DocsDbContext-1;Trusted_Connection=True;MultipleActiveResultSets=true" } }

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.