Submitting a multipart AJAX form with CKEditor textarea

OK, the subject of this post is pretty niche, but that’s why I am posting about it because I do it so little I’d only forget about it for the next time!

With ASP.NET MVC if you want to allow a file upload on a form submitted by AJAX then you have to intercept the form submit event and do the submit it yourself via Javascript, rather than using MVC’s helpers. This is detailed in this useful Stackoverflow answer: How to do a aspnet mvc ajax form post with multipart form data

What the post doesn’t mention (as it wasn’t asked for!) was that if your form contains an instance of the popular rich text editor CKEditor then this code alone will not transfer the data the editor contains to the form. I think this must be because the CKEditor is waiting for the submit event to be triggered before it does the copy into the field.

It took a bit of digging, as I have not had to look at the CKEditor API before, but if you take the code from the above link as a start point, then add the following code to somewhere between the event.preventDefault() call and the ajax() call, it seems to work OK.

            for (instance in CKEDITOR.instances) {

Adding CKEditor to an ASP.MVC AJAX dialog

CKEditor is one of the most popular rich text editors for the Web out there, but although I’ve used it many times I’ve never added it to an MVC site before. Although following the instructions is simple enough for a static view, adding it to a dynamically created view within a jQuery dialog box proved a little bit trickier. As usual there are bits and bobs around on the Net about it, but never the whole thing in one place! So I’ve collated what I’ve found, and added some bits I discovered myself.

OK, so say you want to popup an Edit screen in a jQuery dialog, generating the Edit view to go within the dialog on-the-fly. Download the CKEditor and put the scripts into your site, it doesn’t matter what configuration you use. I usually just put it under the Scripts directory. Also download the jQuery plugin jquery.livequery and put it into your site.

You need the following script links in your page header. whatever.js is just the name of a JS file that you are going to create in a minute, obviously change the paths of the CKEditor and livequery scripts if necessary. It is crucial to include the jQuery adaptor.

<script src="@Url.Content("~/Scripts/jquery.livequery.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/ckeditor/ckeditor.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/ckeditor/adapters/jquery.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/whatever.js")" type="text/javascript"></script>

To start with you would put an Ajax.ActionLink on your View with a call to the Edit screen a bit like this (Razor view syntax):

@Ajax.ActionLink("Edit", "Edit", "Whatever", new AjaxOptions { UpdateTargetId = "editWhatever", OnBegin = "showEdit()"})

Where editWhatever is just an empty div somewhere else on the page, I’ll come onto the showEdit() Javascript in a minute.

The Edit view (and view model) would be something like below. Note that for some reason your field must be an Html.TextArea or TextAreaFor, a regular HTML textarea tag does not work, even though it is fine to use that tag in a non-AJAX form.

@model MyProject.ViewModels.WhateverEditViewModel

@using (Ajax.BeginForm("Save", "Whatever", new AjaxOptions { UpdateTargetId = "editWhatever", OnSuccess = "hideEditOnSuccess()" })) 
    @Html.HiddenFor(m => m.Site.Code)

    <div class="question-editor-label" >
       @Html.LabelFor(model => model.WhateverPropertyToEdit)
    <div class="section-editor-field" >
            @Html.TextAreaFor(model => model.WhateverPropertyToEdit)

    <button title="Save" type="submit" value="Save"  >Save</button> 
    <button type="button" value="Cancel" onclick="doCancel()" title="Cancel" >Cancel</button>

And you could probably work out the view model, but here it is:

namespace MyProject.ViewModels
    public class WhateverEditViewModel
        [Display(Name = "Whatever Description")]
        public string WhateverPropertyToEdit { get; set; }

And remember the ‘Save’ controller action method needs to accept HTML, so you have to decorate it with the annotation [ValidateInput(false)].

public ActionResult Save(WhateverEditViewModel passedModel)

Below is the Javascript for the page contained in whatever.js. In the $(document).ready() function it is crucial to use livequery to detect the appearance of the field on the edit form, as it does not exist when the document is first created. Use the jQuery call to ckeditor() to launch CKEditor. The rest should hopefully be obvious.

$(document).ready(function () {

    $('#WhateverPropertyToEdit').livequery(function () {

function showEdit() {
            modal: true,
            width: 1000,
            title: 'Edit Whatever',
            dialogClass: 'edit_whatever_class',

function doCancel() {

function hideEditOnSuccess() {
    if ($('#editWhatever').find(".validation-summary-errors").size() == 0) {
        /* do anything to the 'host' screen you need to here. */

And you should now see the editor appear on your dialog box.