Ajax post JSON 数据到 MVC 获取错误意外令牌 P
Ajax post JSON data to MVC getting error Unexpected token P
这让我抓狂。我有一个页面,我需要在其中为控制器制作一个 JSON post,它将处理它并 return 一个 excel 文件以供下载。到目前为止它似乎 运行 是正确的,但是当它 return 到 ajax 调用时,我得到一个解析错误和消息 "Unexpected token P." 我已经尝试了很多不同的配置和调用方法(标准 MVC ActionRequest 到 WebApi post)和它们的 none 发生了变化。这是我的代码 运行.
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 扩展,我知道这部分是有效的,只是在需要时下载它return编辑。它到达此代码,生成数据并 returning。我只需要看看到底发生了什么。如果有首选的调用方式,请告诉我(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;
}
从这里开始,我不知道为什么这不起作用。我在 Google 上搜索了关于如何在 MVC 中执行此操作的高低搜索(我曾经使用 Web 表单执行此操作并且从未遇到过问题)。我猜我的问题出在 return 或
更改您的 Success 方法以使用 URL 打开新的 window 而不是在当前 window.
中设置框架
所以这个:
$("#tmpFrame").attr('src', 'URL-TO-EXCEL-FILE');
变为:
window.open('URL-TO-EXCEL-FILE');
在绝大多数情况下,这应该完全符合您的要求。有时,根据特定的浏览器设置,用户可能会收到 "Popup Blocked" 消息,但在我使用过的应用程序中,这种情况很少发生。
编辑:
经过补充说明,还有第二个问题。从服务器返回的数据的格式必须与 .ajax() 方法所期望的格式相同,在本例中为 'JSON'。尝试返回一个 JSON 对象,而不是从你的 Action 返回一个 FileStreamResult,它有你需要调用的 URL 来生成 Excel 文件。
return Json(new { URL = 'URL-TO-EXCEL-FILE' });
然后,按照我原来回复中的建议进行操作。
感谢 Kris Hatcher 提供的解决方案。他建议制作两个 ActionResults。一种根据初始请求的参数构建查询字符串的方法。它 return 是一个完整的 URL 参数。然后它使用 returned 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,您会看到 return 数据使用 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 是一个 class 我有 ToExcel(),我扩展了列表项。现在效果很好。
这让我抓狂。我有一个页面,我需要在其中为控制器制作一个 JSON post,它将处理它并 return 一个 excel 文件以供下载。到目前为止它似乎 运行 是正确的,但是当它 return 到 ajax 调用时,我得到一个解析错误和消息 "Unexpected token P." 我已经尝试了很多不同的配置和调用方法(标准 MVC ActionRequest 到 WebApi post)和它们的 none 发生了变化。这是我的代码 运行.
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 扩展,我知道这部分是有效的,只是在需要时下载它return编辑。它到达此代码,生成数据并 returning。我只需要看看到底发生了什么。如果有首选的调用方式,请告诉我(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;
}
从这里开始,我不知道为什么这不起作用。我在 Google 上搜索了关于如何在 MVC 中执行此操作的高低搜索(我曾经使用 Web 表单执行此操作并且从未遇到过问题)。我猜我的问题出在 return 或
更改您的 Success 方法以使用 URL 打开新的 window 而不是在当前 window.
中设置框架所以这个:
$("#tmpFrame").attr('src', 'URL-TO-EXCEL-FILE');
变为:
window.open('URL-TO-EXCEL-FILE');
在绝大多数情况下,这应该完全符合您的要求。有时,根据特定的浏览器设置,用户可能会收到 "Popup Blocked" 消息,但在我使用过的应用程序中,这种情况很少发生。
编辑:
经过补充说明,还有第二个问题。从服务器返回的数据的格式必须与 .ajax() 方法所期望的格式相同,在本例中为 'JSON'。尝试返回一个 JSON 对象,而不是从你的 Action 返回一个 FileStreamResult,它有你需要调用的 URL 来生成 Excel 文件。
return Json(new { URL = 'URL-TO-EXCEL-FILE' });
然后,按照我原来回复中的建议进行操作。
感谢 Kris Hatcher 提供的解决方案。他建议制作两个 ActionResults。一种根据初始请求的参数构建查询字符串的方法。它 return 是一个完整的 URL 参数。然后它使用 returned 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,您会看到 return 数据使用 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 是一个 class 我有 ToExcel(),我扩展了列表项。现在效果很好。