在 ASP.NET 页面中使用 TinyMCE 编辑器回发

Postback with TinyMCE editor in ASP.NET page

我写这段代码是为了在 ASP 页面上使用 TinyMCE(javascript "richtext" 编辑器)。 ASP 页面本身包含一个名为“art_content”的文本框,它生成一个类似“ctl00_hold_selectionblock_art_content[=26”的 ClientID =]".

我遇到的一个问题是制作一个 "safe" 代码,由我的应用程序存储,并在我去客户端时加载回 HTML,然后它 return 到在提交(或回发)之前它是 "safe" 模式,以防止服务器端的 HTML 检查错误。

我的 Javascript 似乎工作正常,但我还是遇到了错误。貌似没用,虽然功能在触发。

求助!

tinymce.init
(
  {
    selector:'#ctl00_hold_selectionblock_art_content',
    plugins:
      ['table link image textcolor pagebreak code visualblocks charmap'],
    toolbar:
      'bold,italic,underline'
  }
);
function SafeCms(text,encode)
{
  if(encode)
  {
    text=text.replaceAll('<','{{');
    text=text.replaceAll('>','}}');
  }
  else
  {
    text=text.replaceAll('{{','<');
    text=text.replaceAll('}}','>');
  }
  return text;
}
$(document).ready
(
  function()
  {
$('#ctl00_hold_selectionblock_art_content').val(SafeCms($('#ctl00_hold_selectionblock_art_content').val(),false));
    $("form").submit
    (
      function()
      {
        tinymce.triggerSave();
        $('#ctl00_hold_selectionblock_art_content').val(SafeCms($('#ctl00_hold_selectionblock_art_content').val(),true));
      }
    );
  }
);

更新:服务器端(页面)出现错误

A potentially dangerous Request.Form value was detected from the client (ctl00$hold$selectionblock$art_content="<p>ab<em>acac</em>ac...").

CallStack:
[HttpRequestValidationException (0x80004005): Um valor possivelmente perigoso Request.Form foi detectado no cliente (ctl00$hold$selectionblock$art_content="<p>ab<em>acac</em>ac...").]
  System.Web.HttpRequest.ValidateString(String s, String valueName, String collectionName) +8818818
  System.Web.HttpRequest.ValidateNameValueCollection(NameValueCollection nvc, String collectionName) +111
  System.Web.HttpRequest.get_Form() +129
  System.Web.HttpRequest.get_HasForm() +8818919
  System.Web.UI.Page.GetCollectionBasedOnMethod(Boolean dontReturnNull) +97
  System.Web.UI.Page.DeterminePostBackMode() +63
  System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +6785
  System.Web.UI.Page.ProcessRequest(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +242
  System.Web.UI.Page.ProcessRequest() +80
  System.Web.UI.Page.ProcessRequestWithNoAssert(HttpContext context) +21
  System.Web.UI.Page.ProcessRequest(HttpContext context) +49
  ASP.content_quality_knownledges_aspx.ProcessRequest(HttpContext context) in c:\Users\Sammuel\AppData\Local\Temp\Temporary ASP.NET Files\root\a3cdd555\dbee70c6\App_Web_e_7yzdu3.2.cs:0
  System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +181
  System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +75

this article 中所建议,您可以在 SaveContent 事件中从编辑器内容中删除违规的 HTML 字符。如有必要,您可以在 BeforeSetContent 事件中恢复它们。

对于 TinyMCE 4,您可以使用此代码:

tinymce.init({
    selector: '#ctl00_hold_selectionblock_art_content',
    plugins: ['table link image textcolor pagebreak code visualblocks charmap'],
    toolbar: 'bold,italic,underline',
    setup: function (editor) {
        editor.on("SaveContent", function (e) {
            e.content = SafeCms(e.content, true);
        });
        editor.on('BeforeSetContent', function (e) {
            e.content = SafeCms(e.content, false);
        });
    }
});

function SafeCms(text, encode) {
    if (encode) {
        return text.replace(/</g, '{{').replace(/>/g, '}}');
    }
    else {
        return text.replace(/{{/g, '<').replace(/}}/g, '>');
    }
}

我在 SafeCms 中使用带有正则表达式的 replace 而不是 replaceAll (Javascript 中默认不存在)。

我遇到了这个问题,在你的 web.config 添加:

<system.web>
    <pages validateRequest="false" />
</system.web>

如果您使用的是 .net 4.0,请确保将此添加到 web.config

<httpRuntime requestValidationMode="2.0" />

实际上你不需要手动替换字符,你可能总是会遇到你没有想到的特殊情况,并且 ASP.NET 由于安全问题而被阻止。

我认为最好的选择是对内容进行编码,然后在服务器端对其进行解码。

我将我的 TinyMCE 内容复制到一个不可见的文本框(这样用户最终不会在他的 HTML 编辑器中看到编码的内容)

function encodeContent(copyToId, htmlContent) {
    var encodedHtml = encodeURIComponent(htmlContent);
    $('#' + copyToId).val(encodedHtml);
}

然后在服务器端我只获取这个文本框的内容并对其进行解码

var decodedHtml = HttpUtility.UrlDecode(this.TextBoxNewContent.Text);

我不知道你是如何初始化你的 TinyMCE 的,但我亲自将它包装在我注册的 JS 函数中,以便在 Page_PreRender 方法中调用。实际上我有更多的参数,这里是一个简化的代码:

protected void Page_PreRender(object sender, EventArgs e)
{
    var script = "createHtmlEditor('"
       + this.tinyMceEditor.ClientID + "','"
       + this.TextBoxNewContent.ClientID + "');";

    var scriptId = "createHtmlEditor_" + this.tinyMceEditor.ClientID;
    ScriptManager.RegisterStartupScript(this, this.GetType(), scriptId, script, true);
}

encodeURIComponent 是原生 JavaScript 函数,HttpUtility 静态 class 位于 System.Web 命名空间

注意:当我说 "invisible" 文本框时,我指的是 CSS 不可见。因为在 ASP.NET Visibility="false" 中将导致您的 HTML 元素未创建!