0

I have an action method which returns an excel file in return. I am calling that action method using ajax. I am getting Requested JSON parse failed.

 $.ajax({
            url: importUrl,
            data: {
                X: "12",
                Y: "12",
                Z: "12"
            },
            success: function (data) {
                alert("S: "+data);
            },
            error: function (jqXHR, exception) {
                var msg = '';
                if (jqXHR.status === 0) {
                    msg = 'Not connect.\n Verify Network.';
                } else if (jqXHR.status == 404) {
                    msg = 'Requested page not found. [404]';
                } else if (jqXHR.status == 500) {
                    msg = 'Internal Server Error [500].';
                } else if (exception === 'parsererror') {
                    msg = 'Requested JSON parse failed.';
                } else if (exception === 'timeout') {
                    msg = 'Time out error.';
                } else if (exception === 'abort') {
                    msg = 'Ajax request aborted.';
                } else {
                    msg = 'Uncaught Error.\n' + jqXHR.responseText;
                }
                console.log(msg);
            }
        });



public ActionResult ExportReportToExcel(string X, string Y, string Z)
        {
            if (HttpContext.Request.UrlReferrer == null)
                TempData["PDFPrevUrl"] = Url.RouteUrl("PageNotFound");
            else if (TempData["PDFPrevUrl"] == null)
                TempData["PDFPrevUrl"] = HttpContext.Request.UrlReferrer.PathAndQuery;

            var customer = _authenticationService.CurrentCustomer;
            if (customer == null)
                return new LmsHttpUnauthorizedResult();

            string filename = "Report";
            try
            {
                XLWorkbook wb = new XLWorkbook(Server.MapPath(@"~/Content/CumulativePerformanceReportTemplate.xlsx"));
                XElement userprogress = XElement.Load(Server.MapPath(@"~/Content/Export.xml")).Element("cumulativeperformancereport");
                int datarow = int.Parse(userprogress.Element("T").Attribute("row").Value.Trim());
                int datacol = int.Parse(userprogress.Element("T").Attribute("col").Value.Trim());
                IXLWorksheet WS = wb.Worksheet(1);
                WS.Cell(datarow, datacol).Value = customer.Name;
                datarow = int.Parse(userprogress.Element("X").Attribute("row").Value.Trim());
                datacol = int.Parse(userprogress.Element("X").Attribute("col").Value.Trim());
                WS.Cell(datarow, datacol).Value = X;
                datarow = int.Parse(userprogress.Element("Y").Attribute("row").Value.Trim());
                datacol = int.Parse(userprogress.Element("Y").Attribute("col").Value.Trim());
                WS.Cell(datarow, datacol).Value = Y;
                datarow = int.Parse(userprogress.Element("Z").Attribute("row").Value.Trim());
                datacol = int.Parse(userprogress.Element("Z").Attribute("col").Value.Trim());
                WS.Cell(datarow, datacol).Value = Z;
                Response.Clear();
                Response.Buffer = true;
                Response.Charset = "";
                Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
                Response.AddHeader("content-disposition", "attachment;filename=" + filename + "_Summary.xlsx");
                using (MemoryStream MyMemoryStream = new MemoryStream())
                {
                    wb.SaveAs(MyMemoryStream);
                    MyMemoryStream.WriteTo(Response.OutputStream);
                    Response.Flush();
                    Response.End();

                }
                return null;
            }

            catch (Exception ex)
            {
                return Redirect(TempData["PDFPrevUrl"].ToString());
            }

        }

Why am I getting this error?

Sonali
  • 2,223
  • 6
  • 32
  • 69
  • Are you sure the controller action should `return null`? Also X declared twice at data argument here, possibly this causing parsing error: `data: { X: "12", Y: "12", X: "12" },`. – Tetsuya Yamamoto Oct 20 '17 at 07:27
  • @Tetsuya Yamamoto that was typography. I made some correction. Yes I am sure the controller action should return null. – Sonali Oct 20 '17 at 07:28

3 Answers3

1

"Requested JSON parse failed" indicating that AJAX call expects to get JSON data as returned value, but the controller action method returns other data type than JSON object.

By reviewing controller flow and omitting some non-relevant code, you will get this:

public ActionResult ExportReportToExcel(string X, string Y, string Z)
{
    // other stuff

    var customer = _authenticationService.CurrentCustomer;
    if (customer == null)
        return new LmsHttpUnauthorizedResult();

    try
    {   
        // other stuff

        return null; // this returns null value instead of expected JSON
    }

    catch (Exception ex)
    {
        return Redirect(TempData["PDFPrevUrl"].ToString());
    }

} 

By default jQuery tries to infer dataType argument based on the MIME type of the response (xml, json, script or html, most recent default is JSON). Hence, you need to return a JSON object through these methods below:

// ContentResult
return Content("message_text", "application/json");

// JsonResult
return Json("message_text", JsonRequestBehavior.AllowGet);

If you want returning file by AJAX to download, you can use window.location or window.location.href to redirect:

$.ajax({
        url: importUrl, // this should be refer to JsonResult action
        data: {
            X: "12",
            Y: "12",
            Z: "12"
        },
        success: function (data) {
            // deal with data response here
            window.location = downloadUrl; // redirect to FileResult action
        },
        error: function (jqXHR, exception) {
            // other stuff
        }
}

// example controller to return Excel binary file
public FileResult DownloadFile(string fileName)
{
    // other stuff
    byte[] content = TempData["something"] as byte[];

    return File(content, "application/vnd.ms-excel", fileName);
}

NB: The explanations above are mostly trivial, your current implementation may differ from given examples.

Similar issues:

Download Excel file via AJAX MVC

jQuery returning "parsererror" for ajax request

Tetsuya Yamamoto
  • 24,297
  • 8
  • 39
  • 61
0

Why use Backend for something like creating an excel file & then downloading it.... its overkill & downloading part is difficut

use something light weight like Javascript on the client side... it will create excel from XML & will download it using the download property...

    var data_type = 'data:application/vnd.ms-excel';
    var table_div = document.getElementById('table_wrapper');
    var table_html = table_div.outerHTML.replace(/ /g, '%20');

Here is Solution

Rohit Kumar
  • 1,777
  • 2
  • 13
  • 26
0

It could be a server side error in sending the file. Have you tried changing the response Content Type to application/vnd.ms-excel ?


I show you a minimal working example

// Server side
public ActionResult GimmeFile()
{
    var bytes = System.IO.File.ReadAllBytes(@"path_to_your_file.xlsx");
    return File(bytes, "application/vnd.ms-excel", "Myfile.xls");
}

Client side with your Ajax call

$.ajax({
    method: 'POST',
    url: '/Home/GimmeFile',
    success: function (data) {
        alert("S: " + data)
    },
    error: function (jqXHR, ex) {
        console.log(ex)
    }
})

Anyway, I don't know what you need to do with the excel file after ajax call, but if your need is to save it to local then you should use the HTML5 < a download> instead

Luca Corradi
  • 2,031
  • 1
  • 16
  • 17
  • how to download this data that we get – Sonali Oct 20 '17 at 08:38
  • Due to javascript security restriction there's no trivial way to save file to filesystem from a web page - You can save file to browser's [local storage](http://www.w3schools.com/HTML/html5_webstorage.asp) - Or check this [library](http://jquery.tiddlywiki.org/twFile.html) Or you can use the HTML tag < a download> that I mentioned before – Luca Corradi Oct 20 '17 at 08:43
  • I want to download this file. then what's the point of using this. – Sonali Oct 20 '17 at 08:44
  • Do you have a button that triggers the ajax call? If so, you can use `Download` – Luca Corradi Oct 20 '17 at 09:02