0

I'm currently working on a project where the previous contractor had an attachments area within our site. The piece works for the most part but has issues when redirecting back after uploading the file, plus I don't like the fact the page does a full page reload just to update a grid to show the uploaded file.

My goal is to instead do an Ajax call for the upload versus form submit. I have added this in, however, the return forces a download of the Json object (using IE 11). I have researched how to get around this and have yet to find any substantial ways around it.

Is it possible to upload a file using Ajax and not send back a download of the Json object?

Below is my code.

View (Upload.cshtml)

@using (Html.BeginForm("Upload", "PM", FormMethod.Post, new { enctype = "multipart/form-data", id = "frmUpload" }))
{
   @Html.ValidationSummary(true)
   <table>
      ...
      <tr>
          <td>@Html.Label("File: ")</td>
          <td>
            <input type="file" name="file" id="file"/>
            @Html.ValidationMessage("file","File is required")
          </td>
      </tr>
      ...

      <tr>
          <td colspan="2">
            <p>
                <button type="submit" class="t-button" id="btnSubmit">
                    Attach</button>
                <button type="button" class="t-button" onclick="CloseAttachmentWindow()">
                    Cancel</button>
            </p>
        </td>
      </tr>
  </table>    
}

<script type="text/javascript">
  $(document).ready(function () {        
    $("#btnSubmit").click(function (e) {
        e.preventDefault();

        if (!$('form').valid())
            return false;

        //Upload document
        $.ajax({
            type: "POST",
            cache: false,
            url: "/PM/Upload",
            dataType: "json",
            contentType: false,
            processData: false,
            data: $('form').serialize(),
            success: function (result) {
                if (result.success) {
                    var window = $("#error").data("tWindow");
                    window.content("<b>Attachment successfully added</b>").title("Success!");
                    window.center().open();

                    CloseAttachmentWindow();
                }
                else {
                    var window = $("#error").data("tWindow");
                    window.content("<b>Error: Unable to Upload Document.  Please try again.  "
                                        + "If this fails, contact the administrators with the below details.</b>"
                                        + '\n' + '\n' + result.Error).title("Error");
                    window.center().open();
                }
            },
            error: function (xhtr, e, e2) {
                var window = $("#error").data("tWindow");
                window.content(e + '\n' + xhtr.responseText, 'error', '');
                window.center().open();
            }
        });
    });
  });
</script>

PMController.cs

[HttpPost]
public ActionResult Upload(HttpPostedFileBase file, FormCollection formcollection)
{
        if (file != null)
        {
            var cntPOC = int.Parse(Session["cntPOC"].ToString());
            try
            {
                var cntFileType = _fileTypeRepo.GetCntFileTypeByMimeType(file.ContentType);
                if (cntFileType == 0)
                    throw new Exception("This file type is not supported");

                var strAttachmentName = formcollection["AttachmentName"];
                var strAttachmentType = formcollection["AttachmentType"];

                var length = file.ContentLength;
                var tmpFile = new byte[length];

                if (tmpFile.Count() > 0)
                {
                    file.InputStream.Read(tmpFile, 0, length);
                    var intAttchmentId = _AttachRepo.GetNextAttachmentId() + 1;

                    var objAttachment = new TBLATTACHMENT
                    {
                        CNTATTACHMENT = intAttchmentId,
                        CNTPOC = cntPOC,
                        CNTFILETYPE = cntFileType,
                        CNTATTACHMENTTYPE = Convert.ToDecimal(strAttachmentType),
                        DTMCREATED = DateTime.Now,
                        STRATTACHMENTTITLE = strAttachmentName,
                        BLBATTACHMENT = tmpFile,
                        STRORIGINALFILENAME = file.FileName,
                        YSNDELETED = 0
                    };

                    _AttachRepo.Add(objAttachment);
                    _AttachRepo.Save();

                    return Json(new { success = true, Error = "" });
                }
                //File not real
                else
                    return Json(new { success = false, Error = "Please select appropriate file" });
            }
            catch (Exception ex)
            {
                logger.LogError("File Upload", ex);

                if (ex.InnerException != null)
                    ModelState.AddModelError("Error", ex.InnerException.ToString());
                else
                    ModelState.AddModelError("Error", ex.Message.ToString());

                TempData["ModelState"] = ModelState;

                return Json(new { success = false, Error = ex.Message });
            }
        }
        else
        {
            logger.LogError("File Upload Error. File was not selected");
            ModelState.AddModelError("Error", "Please select file");
            TempData["ModelState"] = ModelState;

            return Json(new { success = false, Error = "File was not selected" });
        }
}

As is, using this code, I can upload documents, however, I get the prompt to download the Json object upon return.

NOTE Long story short, you cannot do this. I had to learn the hard way and never did find a solution. I did find a way to do it for downloads, but not uploads.

IyaTaisho
  • 863
  • 19
  • 42
  • Its not clear what your asking here. First, you cannot upload files with the code you have shown (using `data: $('form').serialize(),`) and the file will always be `null` in the POST method. You need to use `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)). –  Mar 15 '17 at 06:37
  • And what do you mean _the return forces a download of the Json object_? (and as a side note, your `@Html.ValidationMessage("file","File is required")` is pointless - you do not have any `data-val-*` attributes in the input and your returning json, not a view so it will never be used. –  Mar 15 '17 at 06:39

1 Answers1

-1

Options:

  • Remove change the button type submit to button <input type="button"/>
  • <input type="submit" onclick="return false">
  • return false; or add event handlers

    $("input[type='submit']").click(function() { return false; }); or $("form").submit(function() { return false; });

  • <form onsubmit="return false"> ...</form> in order to avoid refresh at all "buttons", even with onclick assigned.

changing the submit type to button is the optimal one.

NikhilGoud
  • 574
  • 1
  • 5
  • 21
  • None of the above helps with eliminate the issue with the download situation... That just changes how you submit the form. Also, returning false stops the page altogether... It kills the submission to the Controller... – IyaTaisho Mar 14 '17 at 14:35
  • Oh my bad I thought the page was refreshing for every submit, let me work on it – NikhilGoud Mar 14 '17 at 14:49