这通常指的是在 .NET 环境下(特别是 ASP.NET Core)为网页(HTML)创建一个功能丰富的文本编辑框,而不仅仅是原生 <textarea>,这种编辑器通常被称为 富文本编辑器

dotnettextbox网页编辑器
(图片来源网络,侵删)

下面我将从几个方面为你全面介绍:

  1. 为什么需要富文本编辑器?
  2. 如何在 .NET 项目中集成富文本编辑器?
  3. 主流的富文本编辑器选择及代码示例
  4. 后端如何处理富文本内容?
  5. 重要注意事项

为什么需要富文本编辑器?

相比于原生的 <textarea>,富文本编辑器提供了以下强大功能:

  • 所见即所得:用户可以直接在编辑器中像在 Word 中一样编辑文本、设置格式,无需手动编写 HTML 标签。
  • 格式化支持:支持加粗、斜体、下划线、标题、列表、插入图片/链接等。
  • 代码高亮:对于技术博客或文档,可以插入带语法高亮的代码块。
  • 媒体插入:方便地插入图片、视频、表格等。
  • 提升用户体验:界面友好,功能直观,能显著提升内容创作者的效率。

如何在 .NET 项目中集成富文本编辑器?

集成富文本编辑器通常分为两步:

  1. 前端集成:在 HTML 页面中引入编辑器的 JavaScript 和 CSS 文件。
  2. 后端交互:在 .NET Controller 中接收和处理从前端传来的 HTML 内容。

主流的富文本编辑器选择及代码示例

这里介绍几款在 .NET 生态中非常流行且易于集成的编辑器。

dotnettextbox网页编辑器
(图片来源网络,侵删)

TinyMCE (功能强大,商业友好)

TinyMCE 是一款功能非常全面且商业友好的编辑器,社区版免费且功能已足够强大,个人和商业项目都可以免费使用。

步骤:

  1. 安装 NuGet 包 (可选,但推荐)

    dotnet add package TinyMCE.AspNetCore
  2. _Layout.cshtml 或页面中引入脚本和样式

    dotnettextbox网页编辑器
    (图片来源网络,侵删)
    <!-- 在 <head> 中 -->
    <link href="https://cdn.tiny.cloud/1/no-api-key/tinymce/6/tinymce.min.css" rel="stylesheet">
    <!-- 在 <body> 末尾 -->
    <script src="https://cdn.tiny.cloud/1/no-api-key/tinymce/6/tinymce.min.js" referrerpolicy="origin"></script>

    注意:将 no-api-key 替换为你在 TinyMCE 官网 免费获取的 API Key。

  3. 在 Razor 页面 (.cshtml) 中创建编辑器

    @page
    @model YourProject.Pages.CreateModel
    @{
        ViewData["Title"] = "创建文章";
    }
    <h1>创建新文章</h1>
    <form method="post">
        <div class="form-group">
            <label asp-for="Article.Title"></label>
            <input asp-for="Article.Title" class="form-control" />
        </div>
        <div class="form-group">
            <label asp-for="Article.Content"></label>
            <!-- 将 textarea 转换为 TinyMCE 编辑器 -->
            <textarea id="myEditor" asp-for="Article.Content"></textarea>
        </div>
        <button type="submit" class="btn btn-primary">发布</button>
    </form>
    <script>
        tinymce.init({
            selector: '#myEditor',
            plugins: 'advlist autolink lists link image charmap print preview anchor',
            toolbar: 'undo redo | formatselect | bold italic backcolor | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | removeformat | help'
        });
    </script>
  4. 在 Page Model (Create.cshtml.cs) 中定义模型

    using Microsoft.AspNetCore.Mvc;
    using Microsoft.AspNetCore.Mvc.RazorPages;
    using System.ComponentModel.DataAnnotations;
    namespace YourProject.Pages
    {
        public class CreateModel : PageModel
        {
            [BindProperty]
            public Article Article { get; set; }
            public void OnGet()
            {
                Article = new Article();
            }
            public IActionResult OnPost()
            {
                if (!ModelState.IsValid)
                {
                    return Page();
                }
                // TODO: 将 Article.Content (HTML) 保存到数据库
                //  _context.Articles.Add(Article);
                // _context.SaveChanges();
                return RedirectToPage("/Index");
            }
        }
        public class Article
        {
            public int Id { get; set; }
            [Required]
            public string Title { get; set; }
            [Required]
            public string Content { get; set; } // 这个字段将存储完整的 HTML
        }
    }

CKEditor 5 (现代、灵活)

CKEditor 5 是另一款非常优秀的现代编辑器,模块化设计,可定制性极高。

步骤:

  1. 通过 CDN 引入

    <!-- 在 <head> 中 -->
    <link href="https://cdn.ckeditor.com/ckeditor5/39.0.1/classic/ckeditor.css" rel="stylesheet">
    <!-- 在 <body> 末尾 -->
    <script src="https://cdn.ckeditor.com/ckeditor5/39.0.1/classic/ckeditor.js"></script>
  2. 在 Razor 页面中创建编辑器

    <textarea id="editor" asp-for="Article.Content"></textarea>
    <script>
        ClassicEditor
            .create(document.querySelector('#editor'), {
                // 配置选项
                toolbar: ['heading', '|', 'bold', 'italic', 'link', 'bulletedList', 'numberedList', 'blockQuote'],
                heading: {
                    options: [
                        { model: 'paragraph', title: 'Paragraph', class: 'ck-heading_paragraph' },
                        { model: 'heading1', view: 'h1', title: 'Heading 1', class: 'ck-heading_heading1' },
                        { model: 'heading2', view: 'h2', title: 'Heading 2', class: 'ck-heading_heading2' }
                    ]
                }
            })
            .then(editor => {
                console.log('Editor was initialized', editor);
            })
            .catch(error => {
                console.error(error);
            });
    </script>

后端处理方式与 TinyMCE 完全相同,都是接收一个包含 HTML 的字符串。


Quill.js (轻量、API 友好)

Quill 是一个现代化的编辑器,以其模块化的 API 和简洁的设计而闻名。

步骤:

  1. 通过 CDN 引入

    <!-- 在 <head> 中 -->
    <link href="https://cdn.quilljs.com/1.3.6/quill.snow.css" rel="stylesheet">
    <!-- 在 <body> 末尾 -->
    <script src="https://cdn.quilljs.com/1.3.6/quill.js"></script>
  2. 在 Razor 页面中创建编辑器

    <!-- 创建一个容器来放置编辑器 -->
    <div id="editor" style="height: 200px;"></div>
    <!-- 隐藏的 textarea 用于表单提交 -->
    <textarea id="hiddenContent" asp-for="Article.Content" style="display: none;"></textarea>
    <script>
        var quill = new Quill('#editor', {
            theme: 'snow',
            modules: {
                toolbar: [
                    ['bold', 'italic', 'underline', 'strike'],
                    ['blockquote', 'code-block'],
                    [{ 'list': 'ordered'}, { 'list': 'bullet' }],
                    ['link', 'image'],
                    ['clean']
                ]
            }
        });
        // 当编辑器内容变化时,同步到隐藏的 textarea
        quill.on('text-change', function() {
            document.getElementById('hiddenContent').value = quill.root.innerHTML;
        });
    </script>

    注意:Quill 不直接绑定到 textarea,而是通过一个隐藏的 textarea 来同步 HTML 内容以供表单提交。


后端如何处理富文本内容?

后端的核心任务是安全地存储和显示用户输入的 HTML。

存储

  • 数据库字段类型:将存储 HTML 的字段类型设置为 NVARCHAR(MAX) (SQL Server) 或 TEXT/LONGTEXT (MySQL) 等能存储长文本的类型。
  • 不要信任用户输入:永远不要直接将用户提交的 HTML 原样存入数据库或直接显示在页面上,这存在巨大的 XSS (跨站脚本攻击) 风险。

显示/输出

  • 使用 Razor 的 @Html.Raw()

    • 当你从数据库读取内容并希望在页面上以 HTML 形式渲染时,可以使用 @Html.Raw(Model.Content)
    • ⚠️ 警告@Html.Raw() 会原样输出 HTML,如果内容中包含恶意脚本(如 <script>alert('hack')</script>),就会被执行。@Html.Raw() 只应该用于你完全信任的内容,例如你自己后台编辑的文章。
  • 使用 HTML 编码/净化库 (推荐)

    • 对于用户生成的内容,最佳实践是使用一个库来“净化” HTML,即移除所有危险的标签和属性,只保留安全的标签(如 <p>, <strong>, <em>, <a>, <img> 等)。
    • .NET 内置编码:默认情况下,Razor 引擎会对所有输出进行 HTML 编码。@Model.Content 会把 <p> 显示为 &lt;p&gt;,这是防止 XSS 的第一道防线。
    • 推荐库: HtmlSanitizer 是一个非常流行的 .NET HTML 净化库。

    使用 HtmlSanitizer 的示例:

    1. 安装 NuGet: dotnet add package HtmlSanitizer

    2. 在 Controller 或 Page Model 中使用:

      using Ganss.XSS;
      // ...
      public class MyModel
      {
          public string UserContent { get; set; }
      }
      public IActionResult Display()
      {
          var model = new MyModel { UserContent = "<p>这是安全的 <strong>文本</strong>。</p><script>alert('危险!');</script>" };
          var sanitizer = new HtmlSanitizer();
          // 只允许保留这些标签和它们的属性
          sanitizer.AllowedTags = new[] { "p", "strong", "em", "a", "img", "ul", "ol", "li" };
          sanitizer.AllowedAttributes.Add("href");
          sanitizer.AllowedAttributes.Add("src");
          // 净化 HTML
          model.UserContent = sanitizer.Sanitize(model.UserContent);
          return View(model);
      }
    3. 在视图中直接输出:

      @* 因为已经净化过,所以可以安全地使用 @Html.Raw *@
      <div class="article-content">
          @Html.Raw(Model.UserContent)
      </div>

      或者,如果净化后的内容不包含任何危险的 <script>,也可以直接输出 Razor 会自动编码,但净化后的内容是安全的,@Html.Raw 更合适。


重要注意事项

  1. XSS 安全永远是第一位:永远不要对用户提交的 HTML 内容掉以轻心,要么使用 @Html.Raw() 并确保内容来源可信,要么使用 HTML 净化库。
  2. 文件上传:如果编辑器支持图片上传,你需要自己实现一个安全的文件上传接口,要验证文件类型、大小,并将文件存储在非 Web 可直接访问的目录(或使用 CDN),然后返回一个安全的 URL。
  3. 性能:富文本编辑器通常比 <textarea> 更“重”,加载需要更多资源,对于简单的文本输入,应避免使用。
  4. 移动端兼容性:在选择编辑器时,考虑其在移动设备上的表现,Quill 和 CKEditor 5 在这方面做得不错。
编辑器 优点 缺点 适用场景
TinyMCE 功能全面,文档好,商业友好,社区版免费 相对较“重”,高级功能需付费 功能要求高的博客、CMS、企业应用
CKEditor 5 现代,模块化,API 强大,可定制性高 学习曲线稍陡,高级功能需付费 需要高度定制和现代化 UI 的项目
Quill.js 轻量,API 友好,设计简洁 生态系统相对较小,高级功能需付费 注重性能和简洁 API 的项目

对于大多数 .NET TinyMCECKEditor 5 是最稳妥和功能强大的选择,而 Quill 则适合对性能和 API 有特殊要求的场景。

希望这份详细的指南能帮助你成功在 .NET 项目中集成富文本编辑器!