2

I read some articles that is not possible to save files using Ajax.BeginForm.

I have a form in MVC5 that uses Ajax.BeginForm so the user has a nice responsive app without page refresh.

Now, the requirement is to add 4 fields that will hold files (file upload).

Also read that maybe with jquery.form.js this is possible.

So my questions are about other approach is this make any sense:

  1. The form keep the Ajax.BeginForm
  2. The user enters data into the form.
  3. When user needs to load a file into the form, then I was thinking on uploading that file to server on the fly and store there temporarily.
  4. When the form is saved, on server side I can get temp files and then save them.
halfer
  • 19,824
  • 17
  • 99
  • 186
VAAA
  • 14,531
  • 28
  • 130
  • 253
  • You cannot use `Ajax.BeginForm()` to upload files. You can however use `$.ajax()` with `FormData` - refer [this answer](http://stackoverflow.com/questions/29293637/how-to-append-whole-set-of-model-to-formdata-and-obtain-it-in-mvc/29293681#29293681) (but its a bit unclear why you want to post the files and the form data separately) –  Nov 17 '16 at 00:48
  • @StephenMuecke thanks, so that means I can upload form data + upload files at the same time using $.ajax and formdata? – VAAA Nov 17 '16 at 00:55
  • Sure - `var formdata = new FormData($('form').get(0));` will serialize your form controls including the file inputs. You just need to set the correct ajax options as per the link. –  Nov 17 '16 at 00:59

3 Answers3

2

Please check below code for save separate Form Data and File Upload :

View with Ajax.BeginForm

@using (Ajax.BeginForm("", "", new AjaxOptions
{
    HttpMethod = "POST",
}, new { @id = "UploadFileForm", @class = "form-horizontal" }))
{
 <div class="col-sm-3">
            <label>Browse</label>
            <input type="file" id="file" name="file" />
            <p class="help-block">Supported format .doc,.docx,.pdf</p>
        </div>
        <div class="col-xs-12">
            <button type="button" value="Add" id="Addbtn" class="btn btn-primary">
                <i class="fa fa-plus-square"></i>&nbsp;Add
            </button>
        </div>
        }

File Upload Button Click Event :

 $("#Addbtn").click(function () {
            // --- code for upload resume
            var formdata = new FormData();
            var getfile = document.getElementById('file');
            for (i = 0; i < getfile.files.length ; i++) {
                formdata.append(getfile.files[i].name, getfile.files[i]);
            }
            function isvalidFileFormat() {
                if (getfile.files.length > 0 ) {
                    var extention = $('#file').val().split('.');
                    var data;
                    $.each(extention, function (index, value) {
                        if (index == 1) {
                            data = value;
                        }
                    });

                    if (data == "pdf" || data == "docx" || data == "doc") {
                        return "";
                    }
                    else {
 return "<p>Please choose .pdf, .docx, .doc file only." + "</p>\n";
                    }
                }
                else 
                    return "";
                }
            }
            if (summary) { CustomAlert(summary); return false; } else {
                var TestModel = {
                    "Id": $("#hdnId").val()
                };
                $.ajax(
                 {
                 //Save Main Form Data
                     url: '/TestController/TestAction/',
                     type: "Post",
                     async: false,
                     dataType: "json",
                     data: JSON.stringify(TestModel), 
                     contentType: "application/json;charset=utf-8",
                     success: function (result) {
                     // After saving main data you can save this file for same user
                         formdata.append("Userid", result.id);
                         $.ajax({
                             url: '/TestController/Fileupload',
                             data: formdata,
                             contentType: false,
                             processData: false,
                             async: false,
                             type: 'POST',
                             success: function (data) {
                                 $("#YourDivName").html(data);
                             }
                         });
                         $("#file").val(null);
                     }
                 });
                return true;
            }
        });

Here is the code for file upload

/// <summary>
        ///File Upload
        /// </summary>
        /// <param name="Userid"></param>
        /// <returns></returns>
        [HttpPost]
        public ActionResult Fileupload(int Userid = 0)
        {
            string path = string.Empty;
            string filename = string.Empty;
            string fileExtention = string.Empty;
            string withoutEXT = string.Empty;
            string ResumeFilePath = string.Empty;
            string ChangeFileName = string.Empty;
            bool uploadStatus = false;
            if (Request.Files != null && Request.Files.Count > 0)
            {

                for (int i = 0; i < Request.Files.Count; i++)
                {
                    HttpPostedFileBase file = Request.Files[i];
                    if (file.ContentType == "application/pdf" || file.ContentType == "text/rtf" || file.ContentType == "application/doc"
                        || file.ContentType == "application/vnd.openxmlformats-officedocument.wordprocessingml.document")
                    {
                        filename = Path.GetFileNameWithoutExtension(file.FileName);
                        fileExtention = Path.GetExtension(file.FileName);
                        withoutEXT = fileExtention.Replace(".", "");

                        ChangeFileName = filename + "_" + locationid + fileExtention;

                        var ifExistPath = "/Uploads/Files/" + ChangeFileName;
                        var FileVirtualPath = System.IO.Path.Combine(Server.MapPath("/Uploads/Files/"), ChangeFileName);
                        path = Path.Combine(Server.MapPath("~/Uploads/Files/"), ChangeFileName);

                        //delete file
                        
                        if (System.IO.File.Exists(path))
                        {
                            System.IO.File.Delete(path);
                        }
                        if (ifExistPath != FileVirtualPath)
                        {
                            file.SaveAs(path);
                            uploadStatus = true;
                        }
                        else
                        {
                        }
                    }
                    else
                    {
                        ModelState.AddModelError("", "Please upload a PDF or Doc or rtf File");
                        // return View("", model);
                    }
                    if (uploadStatus && path != string.Empty)
                    {

                        ResumeFilePath = "/Uploads/Files/";
                    //Add code for save this file in database here 
                    }
                }
            }
            return PartialView("Test", objMaster);
        }

Hope this will help you !!

Laxman Gite
  • 2,248
  • 2
  • 15
  • 23
2

Add this

  $("body").on("submit", "#frmAddProduct", function (e) {
            var form = e.target;
            if (form.dataset.ajax) {
                e.preventDefault();
                e.stopImmediatePropagation();
                var xhr = new XMLHttpRequest();
                xhr.open(form.method, form.action);
                xhr.onreadystatechange = function () {
                    if (xhr.readyState == 4 && xhr.status == 200) {
                        if (form.dataset.ajaxUpdate) {
                            var updateTarget = document.querySelector(form.dataset.ajaxUpdate);
                        }
                    }
                };
                if ($("#frmAddProduct").valid()) { xhr.send(new FormData(form)); }
            } return true;
        });
Karan Singh
  • 876
  • 1
  • 6
  • 12
  • It's a shame there isn't more explanation with this answer as it's absolutely right and the most simple implementation. The jQuery effectively highjacks the form's submission and adds the files (along with the rest of the form) to the request. There's also the `ajaxUpdate` part which is a nice touch, so you can handle the response with the element you would have set on an Begin.Ajax – JDandChips Oct 10 '22 at 17:24
1

You cannot use the MVC Ajax helper with files upload. Instead, you can use the jquery form plugin, on a normal Html.BeginForm().

Example:

<form id="myForm" url="/Home/Upload" method="post" enctype="multipart/form-data">
    <label>File</label>
    <input name="file" type="file" />
</form>

<script>
    function bindAjaxForm(selector, onComplete, beforeSerialize) {
        var form = $(selector);
        $.validator.unobtrusive.parse(selector);
        form.data("validator").settings.submitHandler = function (frm) {
            $(frm).ajaxSubmit({
                beforeSerialize: function ($form, options) {
                    if (typeof (beforeSerialize) === "function") {
                        beforeSerialize($form, options);
                    }
                },
                complete: function (response, statusText) {
                    if (typeof onComplete === "function") {
                        onComplete(response, statusText);
                    }
                }
            });
        }
    };

    bindAjaxForm("#myForm", function(data, status) {
        alert("complete");
        console.log(arguments);
    });
</script>

You use the onComplete and beforeSerialize callbacks to handle the response.

onComplete is called after the AJAX is done, and if you console.log its arguments, you will see it contains the AJAX response (json / html).

Try something like this:

bindAjaxForm("#myForm", function(data, status) {
    $("#container").html(data);
});
Catalin
  • 11,503
  • 19
  • 74
  • 147
  • Thanks, while this method works, how do you specify targetId and insertionMode.Replace so that the returned partialView can be inserted in a specific div. – Manish Mar 11 '17 at 12:39
  • I've edited the answer. You have to manually handle the AJAX response. – Catalin Mar 12 '17 at 09:20