Using CKEditor with NET MVC Razor

At work, we have a project coming up that requires content to be constructed by the user. For content entry, we will implement a WYSIWYG editor to give users a familiar set of tools to interact with. There are a plethora of WYSIWYG editors available on the web our chosen one is CKEditor
The CKEditor offers a rich tool set that can be tailored to meet the requirements for content entry. CKEditor comes with well written documentation on a well put together website which is a huge selling point.

Getting Started

To get started, and throw in a quick plug, I am going to use the default .NET MVC web project template to give us a head start. All you have to do is create the default project in visual studio. We have our project, the next step is to download the CKEditor. The current version at the time of writing is 4.7. Once downloaded, unzip the contents (should be a single directory called “ckeditor”) and copy to the root directory in the website.

Implementation

Lets just get the CKEditor loaded on a page in the website. Firstly the JS files for CKEditor need to be included on the web page, include the required JS files into the master page (or just onto the web page the ckeditor is required on) of the project for the moment as shown below.

<script src="ckeditor/ckeditor.js"></script>
<script src="ckeditor/adapters/jquery.js"></script>

ckeditor.js is the main JS file that holds all the code that makes up the CKEditor. I always utilise the JQuery framework to assist with JS coding on a website as it just makes things a lot easier. So in order to get the CKEditor working with JQuery the jquery.js adapter is required. In order to get the editor working, some JS is required in order to convert a DOM element into the CKEditor. You can use a div, p or textarea, I recommend using a textarea because the textarea is a reasonable fallback when the browser doesn’t have JS enabled.

<textarea id="my-textarea"></textarea>

Above is the textarea I have added to the web page so it can be converted into a ckeditor. I never use inline JS, so I have added the code below to the main external JS file (js/mylibs/boilerplate.js). The code is basically saying when the document had loaded, convert the specified selector into a ckeditor. If the selector doesn’t match any elements in the DOM, then nothing happens.

$(function () {
    $('#my-textarea').ckeditor();
});

Provided you have everything in place correctly, you should see something resembling the screenshot below. The textarea has been converted into a CKEditor offering a rich set of content formatting tools. Super!

installation

Sending Content to the Server

So we have our CKEditor on the page, next step is to send the content added by the user to the server so it can be stored or whatever needs to be done with it. With the .NET MVC framework, a process known as model binding is used to send data from the client to a method in a controller on the server. Model binding will take the form values or query string values and try to set those values on the properties of an object instance (the view model), that object is then passed to a method on a controller.

Lets create a view model that will hold the content that is created by the user via the ckeditor.

namespace CKEditorExample.ViewModels.Content
{
    public class ContentViewModel
    {
        public string Text { get; set; }
    }
}

The Text property will have the user content set on it automatically by MVC 3 before it is passed into a controller method. Next step is to modify the razor view page that shows the ckeditor to tell MVC to bind the textarea to the view model that we just created. Razor provides lots of useful helper methods, particular to do with setting up HTML form elements for model binding. The code for the razor view for the content submission is shown below.

@model CKEditorExample.ViewModels.Content.ContentViewModel

@{
    ViewBag.Title = "Content Entry";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>Content Input</h2>

<form method="post" action="/Content/Submit">
@Html.TextAreaFor(x => x.Text)

<p><input type="submit" value="Submit" /></p>
</form>

At the top on the view the model is declared, so now the textarea can be binded to a property on our model. As you can see we are using the razor Html.TextAreaFor to bind a textarea to the Text property on our view model, so when the form is submitted the value in the textarea at the time of submission should be set on the Text property. You may notice that the form is being submitted to /Content/Submit, I have created another razor view / controller method to handle the form submission and display a web page showing the content from the ckeditor that was sent to the server. The ContentController has two methods now, Index which returns a view that displays the form, and Submit that takes care of the form submission.

using System;
using System.Web.Mvc;
using CKEditorExample.ViewModels.Content;

namespace CKEditorExample.Controllers
{
    public class ContentController : Controller
    {
        [HttpGet]
        public ActionResult Index()
        {
            return View();
        }

        [HttpPost]
        [ValidateInput(false)]
        public ActionResult Submit(ContentViewModel model)
        {
            ViewBag.Text = model.Text;
            return View();
        }
    }
}

Above the Submit method shown in the controller above are a couple of attributes. HttpPost stipulates that only POST requests are accepted. The second attribute ValidateInput is telling MVC not to validate the user input, without this when submitting the form you will see the error message shown below.

[HttpRequestValidationException (0x80004005): A potentially dangerous Request.Form value was detected from the client…” exception is thrown because there is HTML being sent to the server. The [ValidateInput(false)] attribute will prevent this error happening, however we are opening ourselves up to a security vulnerability. So, to handle this you can encode the HTML before it is saved a database, or run checks on the content to ensure there isn’t any malicious HTML, such as script tags for JS code blocks. This will allow all our properties on the model to have HTML passed to the server, if your not keen for that you can add [AllowHtml] above the property that is permitted to accept HTML, thus removing the need for the [ValidateInput(false)] attribute.

So submitting the form in the state as shown below.

content_submission

Will result in the web page shown below.

content_submitted

As you can see the HTML that is created by the CKEditor has been sent to the server and is now displayed in the response. This demonstrates creating a CKEditor and sending the content entered by a user to the server.