MVC 5 prevent page refresh on form submit

13,873

Solution 1

So, after much research and attempts. This is my solution:

Using https://github.com/blueimp/jQuery-File-Upload/wiki

HTML:

Earlier I was using a hidden file upload control and triggering its click via a span. But because of security issues a file input which is opened by javascript can't be submitted by javascript too.

<div class="col-md-7">
    <div class="fileupload-buttonbar">
        <label class="upload-button">
            <span class="btn btn-success btnHover">
                <i class="glyphicon glyphicon-plus"></i>
                <span>Add files...</span>
                <input id="fileUpload" type="file" name="files"/>
            </span>
        </label>
     </div>
</div>

Javascript:

$('#fileUpload').fileupload({
    autoUpload: true,
    url: '/Attachment/UploadTempFileToServer/',
    dataType: 'json',
    add: function (e, data) {
        var fileName = data.files[0].name;
        var ext = fileName.substr(fileName.lastIndexOf('.'), fileName.length);

        var attachment = {
            AttachmentName: fileName,
            Extension: ext
        }

        var fileUniqueName = id + ext;

        //Sending the custom attribute to C#
        data.formData = {
            fileUniqueName: fileUniqueName
        }

        data.submit().success(function (submitData, jqXhr) {
            attachment.Path = submitData.path;

            //Add the attachment to the list of attached files to show in the table.
            $scope.attachmentControl.files.push(attachment);
            //Since this is not a direct angular event.. Apply needs to be called for this to be bound to the view.
            $scope.$apply();

        }).error(function (errorData, textStatus, errorThrown) {

        });
    },
    fail: function (data, textStatus, errorThrown) {

    }
});

C#:

public virtual ActionResult UploadTempFileToServer(string fileUniqueName)
    {
        //Getting these values from the web.config.
        var folderPath = fileStorageServer + fileStorageFolder + "\\" + tempFileFolder + "\\";

        var httpPostedFileBase = this.Request.Files[0];
        if (httpPostedFileBase != null)
        {
            httpPostedFileBase.SaveAs(folderPath + fileUniqueName);
        }
        return Json(new
            {
                path = folderPath + fileUniqueName
            },
            "text/html"
        );
    }

Solution 2

To answer #2 (and assuming you're using jQuery):

$(document).on('submit', '#attachmentForm', function(event){

    event.preventDefault();

    // everything else you want to do on submit
});

For #1, unfortunately, unless a browser supports XMLHttpRequest2 objects (which I don't believe IE9 does), you can't send file data via ajax. There are plugins that let you submit the form to a hidden iframe, though. I think Mike Alsup's Form plugin has that ability: http://malsup.com/jquery/form/#file-upload

Share:
13,873
ArjaaAine
Author by

ArjaaAine

I am a day developer who morphed into a night developer!

Updated on June 04, 2022

Comments

  • ArjaaAine
    ArjaaAine almost 2 years

    yBrowser: IE9 Technologies: MVC5

    I am mainly using Angular for everything on my page. (Single Page App).

    But because I am working with IE9, I can't use FileAPI.. So, I decided to go with MVC's Form Actions to get HttpPostedFileBase in my controller methods to handle fileupload.

    Html Code: (Is present in a modal)

    @using (Html.BeginForm("UploadTempFileToServer", "Attachment", FormMethod.Post, new { enctype = "multipart/form-data", id = "attachmentForm" }))
    {
        <div>
            <span id="addFiles" class="btn btn-success fileinput-button" ng-class="{disabled: disabled}" onclick="$('#fileUpload').click();">
                <span>Add files...</span>
            </span>
            <input id="fileUpload" type="file" name="files" class="fileInput" onchange="angular.element(this).scope().fileAdded(this)" />
        </div>
        <div>
            <span class="control-label bold">{{currentFilePath}}</span>
            <input name="fileUniqueName" value="{{fileUniqueName}}" />
            <input id="attachmentSubmit" type="submit" value="Upload File" />
        </div>
    }
    

    MVC Controller:

    public void UploadTempFileToServer(IEnumerable<HttpPostedFileBase> files, string fileUniqueName)
        {
            var folderPath = fileStorageFolder;
    
            foreach (var file in files)
            {
                if (file.ContentLength > 0)
                {
                    file.SaveAs(folderPath + fileUniqueName);
                }
            }
        }
    

    Question #1: Does anyone know of a way to send the HttpPostedFileBase data to the controller, without using form's submit action?

    I don't mind using Jquery if need be. I have tried hijacking the form's submit action and that didn't work. I tried sending the file control's data using non submit button event, but no luck there either.

    If not:

    Question #2 How do I prevent the page from going to /Attachment/UploadTempFileToServer after the execution of submit is completed?

  • ArjaaAine
    ArjaaAine over 9 years
    But if I use the above logic, won't the call to my mvc controller be stopped?
  • ArjaaAine
    ArjaaAine over 9 years
    And yeap IE9 doesn't support XHR2.. How i wish our firm used IE10+ because I could have simply used the FileAPI to do my uploading :/
  • Tieson T.
    Tieson T. over 9 years
    @ArjaaAine For your first comment: yes. You would have to use some form of JavaScript to send the POST via ajax, although that has the limitation we've already mentioned - the Form plugin will handle that for you, though. Otherwise, if you simply don't want to have to supply a view for the upload action, you would have to redirect to a different action (perhaps back to the original action?). So, the last line of the POST action might read return RedirectToAction("someaction", "somecontroller");
  • ArjaaAine
    ArjaaAine over 9 years
    Ah I see. Yea, unfortunately I can't use the redirectToAction.. since I am using MVC Views (but angular $scope and models) the redirect causes angular to lose its data and hence the user loses their work. I am working on trying to implement the library you suggested :-).
  • ArjaaAine
    ArjaaAine over 9 years
    I ended up using: github.com/blueimp/jQuery-File-Upload/wiki, as I found its implementation easier to use. But thanks a lot for your help :-)