【问题标题】:Ajax post JSON data to MVC getting error Unexpected token PAjax 将 JSON 数据发布到 MVC 得到错误 Unexpected token P
【发布时间】:2015-03-09 16:47:28
【问题描述】:

这让我发疯了。我有一个页面,我需要在其中向控制器发布 JSON,它将对其进行处理并返回一个 Excel 文件以供下载。到目前为止,它似乎运行正常,但是当它返回到 ajax 调用时,我收到一个解析器错误和消息“意外的令牌 P”。我已经尝试了很多不同的配置和调用方法(标准 MVC ActionRequest 到 WebApi 帖子),但它们都没有改变。这是我正在运行的代码。

JavaScript:

       var treatmentplan = {"PlanRecordStatusId":"1","PlanRecordDateBegin":"","PlanRecordDateEnd":"","ClientClaimNumber":"","PatientNumber":0,"requestAction":3};

        $.ajax({
            //global: true,
            //url: '/home/ExcelRpt',
            url: '/api/TreatmentPlanExcel',
            type: 'POST',
            dataType: 'json',
            data: treatmentplan,
            //contentType: 'application/json; charset=utf-8',
            success: function (data) {
                //var msg = data.Message;
                //$('#results').html(msg);
                $("#tmpFrame").attr('src', 'URL-TO-EXCEL-FILE');
            }
            , error: function (jqXHR, exception, error) {
                if (jqXHR.status === 0) {
                    alert('Not connect.n Verify Network.');
                } else if (jqXHR.status == 404) {
                    alert('Requested page not found. [404]');
                } else if (jqXHR.status == 500) {
                    alert('Internal Server Error [500].');
                } else if (exception === 'parsererror') {
                    alert('Requested JSON parse failed.');
                } else if (exception === 'timeout') {
                    alert('Time out error.');
                } else if (exception === 'abort') {
                    alert('Ajax request aborted.');
                } else {
                    alert('Uncaught Error.n' + jqXHR.responseText);
                }
                $('#log').html(error.message);
            }
        });

这是 C# 代码(WebApi 和 MVC 控制器版本),我不打算包含我的 ToExcel 扩展,我知道这部分有效,只是在返回时下载它。它正在到达此代码,生成数据并返回。我只需要看看到底发生了什么。如果有首选的调用方式,也请告诉我(WebApi 或 MVC)

C#

Web API 版本

    public HttpResponseMessage Post(TreatmentPlanRequest tpRequest) {
        tpRequest.Verify();
        List<TreatmentPlan> tpl = DataAccess.GetReportDap(tpRequest).ToList();

        HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
        var contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
        var package = tpl.ToExcel("TreatmentReport");
        var fileStream = new MemoryStream();
        package.SaveAs(fileStream);
        fileStream.Position = 0;

        result.Content = new StreamContent(fileStream);
        result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");

        return result;

    }

这是 MVC 控制器版本

    [HttpPost]
    public ActionResult ExcelRpt(TreatmentPlanRequest tpRequest) {
        tpRequest.Verify();            
        List<TreatmentPlan> tpl = DataAccess.GetReportDap(tpRequest).ToList();

        var contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
        var package = tpl.ToExcel("TreatmentReport");
        var fileStream = new MemoryStream();
        package.SaveAs(fileStream);
        fileStream.Position = 0;

        var fsr = new FileStreamResult(fileStream, contentType);
        fsr.FileDownloadName = "TreatmentReport";

        return fsr;


    }

从这里开始,我不知道为什么这不起作用。我在谷歌上搜索了如何在 MVC 中执行此操作(我曾经使用 Web 表单执行此操作并且从未遇到过问题)。我猜我的问题是在退货或

【问题讨论】:

    标签: c# ajax json excel model-view-controller


    【解决方案1】:

    更改您的 Success 方法以使用 URL 打开一个新窗口,而不是在当前窗口中设置一个框架。

    所以这个:

    $("#tmpFrame").attr('src', 'URL-TO-EXCEL-FILE');
    

    变成:

    window.open('URL-TO-EXCEL-FILE');
    

    在绝大多数情况下,这应该完全符合您的要求。有时,根据特定的浏览器设置,用户可能会收到“弹出窗口被阻止”消息,但在我使用过的应用程序中,这种情况很少发生。

    编辑:

    在进一步澄清之后,还有第二个问题。从服务器返回的数据必须与 .ajax() 方法所期望的格式相同,在本例中为“JSON”。不要从您的操作返回 FileStreamResult,而是尝试返回一个 JSON 对象,该对象具有您需要调用以生成 Excel 文件的 URL。

    return Json(new { URL = 'URL-TO-EXCEL-FILE' });
    

    然后,按照我原始回复中的建议进行操作。

    【讨论】:

    • 现在它甚至没有达到成功部分,它不断返回一个解析错误,说 Unexpected Token P,这对我来说毫无意义。
    • 您已经告诉 $.ajax() 方法期待 JSON,但您没有返回 JSON 对象。
    • 我建议使用 MVC 方法,但将其从“ActionResult”更改为“JsonResult”。然后,从 C# 返回一个 JSON 对象,其中包含您需要的内容,而不是返回 FileStreamResult。
    • 我认为 dataType 是设置调用格式,它应该是返回类型吗?我看到的每个例子都有json。有没有excel或者file的dataType?
    • 你必须匹配JS和C#之间的类型。如果一个人期待 JSON 而另一个人发送 FileStream,那么事情将无法正常工作。
    【解决方案2】:

    我要感谢 Kris Hatcher 提供的解决方案。他建议制作两个 ActionResult。从初始请求的参数构建查询字符串的一种。它返回带有参数的完整 URL。然后它使用返回的 url 执行 Window.Open()。

    在我找到的所有示例中,这是唯一对我有用的示例。下面是代码的工作原理。

    JavaScript:

    function TestWebApiReport() {
        var reportData = GetReport();
    
        $.ajax({
            url: '/home/ExcelResults'
            , data: reportData
            , type: 'POST'
            , dataType: 'json'
            , success: function (data) {
                window.open(data.URL);
            }, error: function (jqXHR, exception, error) {
                alert("GRRRRRR!!!")
            }
        });
    }
    

    它创建 JSON 数据,然后将其发布到 JsonResult。这是控制器代码。

    C#

        [HttpPost]
        public JsonResult ExcelResults(ReportRequest tpRequest) {
            StringBuilder sb = new StringBuilder();
            bool firstIn = true;
            sb.AppendFormat("{0}/Home/ExcelRpt", Request.Url.Scheme + "://" + Request.Url.Authority);
            foreach (var prop in tpRequest.GetType().GetProperties()) {
                if (prop.GetValue(tpRequest, null) != null) {
                    if (firstIn) {
                        sb.AppendFormat("?");
                        firstIn = false;
                    } else {
                        sb.AppendFormat("&");
                    }
                    sb.AppendFormat("{0}={1}", prop.Name, prop.GetValue(tpRequest, null));
                }
            }
    
            return Json(new { URL = sb.ToString() }); 
        }
    

    您返回到 JavaScript,您会看到返回数据使用 URL 执行 Window.Open()。然后创建excel文件。这是最后一次调用 (ActionResult)。

        [HttpGet]
        public ActionResult ExcelRpt(ReportRequest tpRequest) {
    
            if (tpRequest.requestAction != RequestAction.Report) {
                throw new Exception("Did not use action request type of 'Report'.");
            }
            tpRequest.requestAction = RequestAction.Report;
            List<Report> tpl = DataAccess.GetReportDap(tpRequest).ToList();
    
            var contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
            var package = tpl.ToExcel("Report");
            var fileStream = new MemoryStream();
            package.SaveAs(fileStream);
            fileStream.Position = 0;
    
            var fsr = new FileStreamResult(fileStream, contentType);
            fsr.FileDownloadName = "TreatmentReport.xlsx";
    
            return fsr;
        }
    

    ReportRequest 是我拥有的一个类和 ToExcel(),我扩展了 List 项。现在这很好用。

    【讨论】:

      猜你喜欢
      • 2017-02-25
      • 1970-01-01
      • 2021-06-05
      • 2014-02-11
      • 1970-01-01
      • 2017-12-06
      • 1970-01-01
      • 1970-01-01
      • 2016-08-05
      相关资源
      最近更新 更多