A couple of years ago I posted my solution for the infamous “A potentially dangerous Request.Form value was detected from the client” error when using TinyMCE with ASP.NET 4.0.

The solution worked (mostly) without turning off request validation.

Since then, I’ve changed my approach slightly; I’ve dropped the Moxiecode TinyMCE ASP.NET assembly and have gone with a purely JavaScript solution. I think it works better, and it’s a lot cleaner and more up to date.

There are a few parts to this:

  1. Implementing TinyMCE JavaScript version
  2. Decoding HTML server-side on POST
  3. Handling TinyMCE re-encoding HTML on Postback

Implementing TinyMCE JavaScript version

Download TinyMCE (just grab the main package, which “contains all you need for production usage”), extract and copy the files into your solution.

Any page that has a TinyMCE text editor will need to include the base js file and a chunk of initialization script to set up all our options.

<script type="text/javascript" src="/_assets/tiny_mce/tiny_mce.js"></script>

<script type="text/javascript" >
    tinyMCE.init({
        mode: "specific_textareas",
        editor_selector: "tinymce",
        encoding: "xml",
        convert_urls: false,
        theme: "advanced",
        plugins: "spellchecker,pagebreak,style,layer,table,advhr,advimage,advlink,iespell,inlinepopups,insertdatetime,preview,media,searchreplace,print,paste,directionality,fullscreen,visualchars,nonbreaking,xhtmlxtras",
        extended_valid_elements: "iframe[src|width|height|name|align]",
        theme_advanced_buttons1: "spellchecker,|,bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,|,styleselect,formatselect,fontselect,fontsizeselect,|,print,fullscreen",
        theme_advanced_buttons2: "cut,copy,paste,pastetext,pasteword,|,search,replace,|,bullist,numlist,|,outdent,indent,blockquote,|,undo,redo,|,link,unlink,anchor,image,cleanup,help,code,|,insertdate,inserttime,preview,|,forecolor,backcolor",
        theme_advanced_buttons3: "tablecontrols,|,hr,removeformat,visualaid,|,sub,sup,|,charmap,emotions,media,advhr,|",
        theme_advanced_toolbar_location: "top",
        theme_advanced_toolbar_align: "left",
        theme_advanced_path_location: "bottom",
        theme_advanced_resizing: true,
        theme_advanced_resize_horizontal: false,
        theme_advanced_styles: "Link to Image: lightbox;Image Right Border: rightbordered;Image Left Border: leftbordered;Darker Text: darker",
        setup: function (ed) {
            ed.onSaveContent.add(function (i, o) {
                o.content = o.content.replace(/&#39/g, "&apos");
            });
        }
    });
</script>

I’ve got all my site-specific configuration in the plugins and themes options; you’ll probably want to change those for your implementation.

There are three key areas here you want to pay attention to.

mode: "specific_textareas",
editor_selector: "tinymce",

These two tell TinyMCE to only initialize textareas with a class attribute containing “tinymce”. That means we won’t accidentally create TinyMCE instances if we’re using other textareas on the page.

encoding: "xml",

The encoding option (off by default) tells TinyMCE to XML-encode all HTML in our textarea on POST. This is critical for ASP.NET.

setup: function (ed) {
    ed.onSaveContent.add(function (i, o) {
        o.content = o.content.replace(/&#39/g, "&apos");
    });
}

Apostrophes will give you a lot of grief unless you explicitly add this onSaveContent() handler to convert them to a safe, encoded string. This is critical for ASP.NET.

Now all we have to do is include a textarea with the right class, and the init() function will take care of setting up TinyMCE for us.

<textarea
    id="htmlBody"
    runat="server"
    class="tinymce"
    rows="40"
    cols="120" />

Easy!

Decode HTML server-side on POST

Because TinyMCE is encoding HTML, we might choose to decode it server-side before storing it in the database. If you don’t decode TinyMCE output now, you’ll need to decode it before rendering anywhere.

public String SystemText
{
    get
    {
        return HttpUtility.HtmlDecode(bodyHtml.Value);
    }
    set
    {
        bodyHtml.Value = value;
    }
}

In codebehind (or wherever else you’re referring to your textarea in code), use HttpUtility to decode TinyMCE’s output when retrieving the value of the textarea for storage.

Handling TinyMCE re-encoding HTML on Postback

TinyMCE is set to encoding=xml, which encodes everything in the textarea on POST. That leads to a bunch of nasty &amp; &gt; etc. instead of real HTML when the page reloads after a Postback.

So, on Postback, we decode the textbox so TinyMCE is starting "clean". Here’s what sample codebehind could look like to do this:

protected void Page_Load(object sender, EventArgs e)
{
    if (IsPostBack)
    {
        if (bodyHtml != null && !string.IsNullOrWhiteSpace(bodyHtml.Value))
        {
            bodyHtml.Value = HttpUtility.HtmlDecode(bodyHtml.Value);
        }
    }
}

I’m very happy with this method; it works great using ASP.NET 4.0 and its more robust page validation model.

More importantly, I don’t have that nasty feeling I’m doing something terrible by setting ValidateRequest="false” in the page declaration!

Search

Site Sections

Recent Posts

Archives

Post Categories

WHS Add-In Tutorial

WHS Blogs

WHS Development