CKeditor and ASP.NET

30. May 2010 11:19

I have seen many developers give and follow bad advice in regards to using CKeditor with ASP.NET, hence I am writing this blog post to give what I believe is the correct advice.

Background

CKeditor is a WYSIWYG text/HTML editor (for websites) developed using JavaScript. It is the successor to FCKeditor, but this time it is super fast, WAI-AA compliant, has a jQuery adaptor and is gaining some pretty nice features. I've used TinyMCE and FCKeditor in the past, both had their advantages and disadvantages, but I think CKeditor has fixed all the the disadvantages of the previous generation of web HTML editors and is now one of the best editors available. Plus it's open source, and free.

A screenshot of CKeditor

The Problem

CKeditor is often used to replace a HTML textarea field in a form, and when the form is submitted the CKeditor content is submitted as HTML. This causes a problem because ASP.NET implements a security feature that blocks posted form data containing HTML, with an error message that reads: “A potentially dangerous Request.Form value was detected". This is Request Validation, and is a preventative method against users submiting bad and malicious data to your application.

90% of the time I see developers deactivating request validation (ValidateRequest=”false”) on their pages and websites just to get CKeditor to work, and this is my message to those developers, and to you, to STOP doing this - and do it properly! Deactivating request validation is taking down a layer of your website's defense mechanism, which I think we can all agree is not the most desirable solution.

Note: FCKeditor, the predecessor to CKeditor, has an offical ASP.NET user control - and CKeditor is having an official one developed too. There are also unoffical CKeditor user controls. What I am able to show/discuss does not necessarily apply to these user controls; as they should already be doing the things I am about to show - apart from the section "Taking it further".

The Solution

CKeditor, thankfully, has an configuration setting specifically to work around ASP.NET's request validation without having to disable it. In CKeditor's config.js we need to add the following:

config.htmlEncodeOutput = true;

Just to ensure things are clear, here is an example config.js file:

CKEDITOR.editorConfig = function (config) {

    config.skin = 'kama';
    config.resize_enabled = false;
    config.toolbarCanCollapse = false;
    config.height = 300;
    config.htmlEncodeOutput = true;

};

The configuration setting above tells CKeditor that the HTML needs to be encoded before posting it back to the server; this works around ASP.NET's request validation because there is no pure HTML being posted back to the server. Next we need to decode it in our code-behind (if you're using WebForms) or our controller (if you're using MVC). I'm going to demonstrate this using two semi-complete examples.

C# MVC Example

The key line of interest is no.13:

public class MyController : System.Web.Mvc.Controller
{
	[HttpPost]
	public ActionResult Create(ViewModel viewModel1)
	{
		if (ModelState.IsValid)
		{
			var entity1 = new Entity();
			entity1.Title = viewModel1.Title;
			
			//Decode the value that CKeditor returned
			entity1.Text = viewModel1.Text
			.Replace("&lt;", "<").Replace("&gt;", ">").Replace("&amp;", "&");
			
			DatabaseService.Save(entity1);
			return RedirectToAction("Index");
		}
		return View();
	}
}

VB.NET WebForms Example

The key line of interest is no.14:

Public Class MyPage
	Inherits System.Web.Page
	
	Protected Sub Button1_Click(ByVal sender As Object, _
		ByVal e As System.EventArgs) Handles Button1.Click
		
		'Do some validation
		
		Dim entity1 As New Entity
		entity1.Title = TextBox1.Text
		
		'Decode the value that CKeditor returned
		entity1.Text = CKTextBox2.Text _
		.Replace("&lt;", "<").Replace("&gt;", ">").Replace("&amp;", "&")
		
		DatabaseService.Save(entity1)
		
		'Do whatever
		
	End Sub
	
End Class

Now that we are decoding posted form data, perhaps we should encode it before we send the form and editor to the user's web browser. It's basically the same as decoding the data, but in reverse. This time I am going to provide shortened examples:

C# MVC Example

viewModel1.Text = entity1.Text
	.Replace("&","&amp;").Replace(">","&gt;").Replace("<","&lt;");

VB.NET WebForms Example

CKTextBox2.Text = entity1.Text _
	.Replace("&","&amp;").Replace(">","&gt;").Replace("<","&lt;")

Taking it further

Now, we have CKeditor fully working with ASP.NET's request validation. But it doesn't stop a malicious user from posting bad HTML code - we need to "sanitize" it. Luckily there is a .NET library for that called AntiXSS. Using this library, we can reduce the chance of users successfully submitted bad data:

//Retrieve CKeditor value
untrustedFormValue = TextBox1.Text
	.Replace("&lt;", "<").Replace("&gt;", ">").Replace("&amp;", "&");

//Sanitize untrusted form value
trustedFormValue = AntiXss.GetSafeHtmlFragment(untrustedFormValue);

Summary

I have shown how you can utilise CKeditor on your ASP.NET website without having to take down the defense mechanism called request validation, and then sanitize the data inputted by the user. However, I have not shown how to use CKeditor when using jQuery/AJAX with ASP.NET - this will be another post that I'm leaving for later!

Twitter Facebook MySpace Digg

Tags: ,

Comments

6/3/2010 10:05:53 AM #

Joe

Hi, thanks for the post.
Have you managed to get ckeditor working with RequiredFieldValidator controls?
Thanks,
Joe

Joe United Kingdom | Reply

6/4/2010 10:17:20 PM #

Simon Bartlett

If the problem is that the field is only validated correctly when the submit button is clicked twice - I had the code to fix that somewhere. I can post another blog post for that if you'd like?

Otherwise, I haven't tried using CKeditor with a RequiredFieldValidator control yet. I may look in to it if I have a spare moment, but if you can send me a test case - then I'll look at the issue for sure!

Simon Bartlett United Kingdom | Reply

6/15/2010 4:02:59 PM #

Joe

Hi Simon, thanks for the reply.
Yes that was the problem.  I solved it by using a customvalidator instead

e.g.

<asp:CustomValidator runat="server" ValidateEmptyText="true" ID="cvIntro" SetFocusOnError="true"
                        Display="Dynamic" ErrorMessage="Please enter an article" ClientValidationFunction="ValidateContentText"
                        ControlToValidate="txtArticle" CssClass="warning"></asp:CustomValidator>

and some JS (note: this this uses jQuery)

    function ValidateContentText(source, args) {
        var controltovalidate = jQuery(source).attr("controltovalidate");
        args.IsValid = ($('#' + controltovalidate).val() != "" && $('#' + controltovalidate).val() != "<br />");
    }

Joe United Kingdom | Reply

6/21/2010 2:53:57 PM #

Desmond Beazley

I would user Server.HtmlDecode(TextBox1.Text);
You need to do this - TextBox1.Text = Server.HtmlDecode(TextBox1.Text);
if redisplaying the page (after validation failure for example).

Desmond Beazley Israel | Reply

6/24/2010 11:17:34 PM #

Simon Bartlett

I wouldn't use Server.HtmlDecode(TextBox1.Text) - because CKeditor only encodes the following three characters respectively: "&", ">", and "<". You may experience unpredicted behaviour when using Server.HtmlDecode with CKeditor, with it decoding parts of the string that were not actually encoded by CKeditor.

Simon Bartlett United Kingdom | Reply

6/29/2010 9:52:42 PM #

Jeremy Meador

I was able to get the text within CKEditor to encode and save it to the server, but whenever there is a postback, CKEditor re-encodes everything, showing paragraph tags and such in the editor (source shows what would be encoded text). What would cause this? Could it be because I am using the Syrinx wrapper control for CKEditor? Are there alternative user controls I should use?

Jeremy Meador United States | Reply

6/30/2010 11:27:28 AM #

Simon Bartlett

I haven't tried any CKeditor .NET user controls; and this blog post is only applicable to using CKeditor without a user control. As I mentioned in the article; the user control you're using should be handling the encoding/decoding - if not maybe there is an issue with it?

Simon Bartlett United Kingdom | Reply

8/21/2010 9:13:49 AM #

bodenuk

Good post

bodenuk United States | Reply

Add comment


(Will show your Gravatar icon)

  Country flag

biuquote
  • Comment
  • Preview
Loading

About Me

I'm 24 years old, and live in the UK. I'm a software/web developer who mostly dabbles in .NET, ASP.NET MVC, C#, JavaScript, jQuery, and CSS.

Month List

Recent Posts