1

I've written some Javascript that allows me to have my MVC forms submit and reload in a specific Div instead of the whole page. This is working for most of the forms I use it in.

Now I'm trying to use this with a form that includes a File object. Originally this view worked like this:

@using (Html.BeginForm
        (
            "_submissionfiles", 
            "Project", 
            FormMethod.Post,
            new { enctype = "multipart/form-data" }
        )
    )
{
    @Html.AntiForgeryToken()
    <div class="form-horizontal">
        @Html.HiddenFor(model => model.ProjectContentId)
        <div class="form-group">
            ...
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.ContentFile, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                <input type="file" id="ContentFile" name="ContentFile" value="ActionHandlerForForm" />
            </div>
        </div>

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Save" class="btn btn-default"/>
            </div>
        </div>
    </div>
}

With a model and controller like this:

public class ProjectContentViewModel
{
    public System.Guid ProjectContentId { get; set; }
    public Guid? ProjectSubmissionId { get; set; }
    //....
    [Display(Name = "Content Type")]
    public int ContentTypeId { get; set; }

    [Display(Name = "Content")]
    public HttpPostedFileBase ContentFile { get; set; }
}

[HttpPost]
[ValidateAntiForgeryToken]
public virtual ActionResult _submissionfiles(ProjectContentViewModel model)
{
    if (!ModelState.IsValid) return View(model);
    UploadedFile fileUploaded = null;
    if (model.ContentFile.ContentLength > 0)
    {
        // handle file stuff
    }
    //...
    db.SaveChanges();
    AddMessage("Content submitted successfully.");
    return View(model);
}

That worked, but would always return as the whole page. Now I've modified the Begin.Form to this:

@using (Html.BeginForm
        (
            "_submissionfiles", 
            "Project", 
            FormMethod.Post,
            new { enctype = "multipart/form-data", id = "submissionFilesForm", @class = "ajaxformsubmit", data_target_div = "ProjectSubmissionPanel" }
        )
    )
{
    //....

This would allow my javascript to handle the form submission, and return the results to the target_div. This works in other forms which do not have a file, but the problem here is when I get into the controller model.ContentFile is Null. I suppose it's something to do with how I have javascript serializing the form.

Here's the javascript:

BindAjaxForm = function() {
    $(".ajaxformsubmit").on("submit", function(e) {
        e.preventDefault(); //This prevents the regular form submit
        // I think this is where things need to get changed
        AjaxAction(this.action, this.method, $(this).serialize(), $(this).attr("data-target-div"))
        // ^^^^^^^^^^
        return false;
    });
};
AjaxAction = function (url, type, data, targetDivName) {
    var targetDiv = $("#" + targetDivName);
    $.ajax({
        url: url,
        type: type,
        data: data, // or this?
        success: function (result) {
            // Load/Refresh a div if we have one.
            if (typeof targetDiv != "undefined") {
                targetDiv.html('');
                targetDiv.html(result);
            }
        },
        error: function (data) {
            alert(data);
        }
    });
    return false;
};

Is there a way in Javascript/Jquery to serialize the form with files intact?

M Kenyon II
  • 4,136
  • 4
  • 46
  • 94
  • What browser are you using? – ataravati Nov 04 '15 at 20:02
  • Chrome, but it could be any of them. – M Kenyon II Nov 04 '15 at 20:05
  • I seem to recall getting around this once by using [FormData](https://developer.mozilla.org/en-US/docs/Web/API/FormData): `data: new FormData(document.getElementById('submissionFilesForm'))` – neilsimp1 Nov 04 '15 at 20:14
  • Trying to figure out if I can do that dynamically, since this javascript method is used by multiple forms. Maybe `var formData = new FormData(document.getElementById(this.id));`. – M Kenyon II Nov 04 '15 at 20:20
  • After further research, I see the JQuery `.serialize` does not handle file input types. Is there another way I can Ajax submit forms that will include file input types? – M Kenyon II Nov 04 '15 at 20:36
  • @M Kenyon II If you want to try and make the `new FormData()` call dynamic, you could pass it like `AjaxAction(this.action, this.method, this.id, ...` and then in AjaxAction just do `data: new FormData(document.getElementById(id))`. Or perhaps just pass `this` and do `data: new FormData(this)` You can do it other ways, of course, but this might get you going. I know FormData will at least include the files, but it also [isn't as compatible with some older browsers](http://caniuse.com/#feat=xhr2). – neilsimp1 Nov 04 '15 at 20:42

0 Answers0