Ajax 将 JSON 数据发布到 MVC 收到错误意外令牌 P
本文关键字:错误 意外 令牌 MVC Ajax JSON 数据 | 更新日期: 2024-11-08 09:15:19
这让我发疯了。我有一个页面,我需要向控制器发布 JSON 帖子,它将处理它并返回一个 excel 文件以供下载。 到目前为止,它似乎运行正常,但是当它返回到ajax调用时,我收到解析器错误和消息"意外令牌P"。 我已经尝试了许多不同的配置和调用方法(标准MVC ActionRequest to 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#
网页接口版本
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中做到这一点(我曾经使用网络表单来做到这一点,从来没有遇到过问题)。 我猜我的问题在退货或
更改 Success 方法以使用 URL 打开一个新窗口,而不是在当前窗口中设置框架。
所以这个:
$("#tmpFrame").attr('src', 'URL-TO-EXCEL-FILE');
成为:
window.open('URL-TO-EXCEL-FILE');
在绝大多数情况下,这应该完全符合您的要求。 有时,根据特定的浏览器设置,用户可能会收到"弹出窗口已阻止"消息,但在我使用过的应用程序中,这种情况很少发生。
编辑:
在进一步澄清之后,还有第二个问题。 从服务器返回的数据必须与 .ajax() 方法期望的格式相同,在本例中为"JSON"。 尝试返回一个 JSON 对象,而不是从您的操作返回 FileStreamResult ,该对象具有生成 Excel 文件所需的 URL。
return Json(new { URL = 'URL-TO-EXCEL-FILE' });
然后,按照我原始回复中的建议进行操作。
感谢Kris Hatcher对此的解决方案。 他建议制定两个行动结果。 从初始请求的参数生成查询字符串。 它返回一个包含参数的完整 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 文件。 这是最后一个调用 (操作结果)。
[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;
}
报告请求是我有一个类,ToExcel(),我扩展了列表项。 现在这工作得很好。