我到处都找到了关于如何实现这一目标的各种信息,但我没有找到任何将它们组合在一起的东西。
我有两个问题:
有更好的方法来实现这一点吗?我不想走上 HTTP
GET
请求的模型绑定之路。我有很多字段,我不想遍历所有内容并为每个字段和我需要提供给 [BindProperty(Name = "whatever", SupportsGet = true)]
的每个属性添加一堆 GET
属性。
我如何最好地处理 Javascript 方面的错误? 警报就可以了,但我有兴趣获取任何错误详细信息以帮助诊断错误发生的原因。下面的控制器示例省略了服务器端的错误处理,但它是存在的并且有效。我是否应该担心 Javascript 中的错误处理?
页面目标:从 ASP.NET Core 8 MVC 页面提交表单,该页面使用整个页面的模型,包括通过表单对模型进行的更改,最终结果是根据所做的选择下载并应用于页面的文件型号。
目标澄清:用户在此网页上选择的选项可能很多。 足以超出 Http GET 允许返回到服务器的限制。 请注意,此页面可能有 10 个组合框/下拉菜单,它们都是多选字段。 每个组合框可以有几千个选定的选项。 不要要求简化。 这是要求的一部分。
使用
_Layout
表示身体等的粗略视图示例:
@using MyNameSpace.ModelNameSpace
@model MyPagesViewModel;
@{
ViewData["Title"] = MyPagesViewModel._PageTitle; //public const string of _PageTitle
}
<div class="pageWrapper">
<form id="MyForm" asp-controller="MyPageController" asp-action="SubmitForm" method="post">
Customer Name: <input type="text" asp-for="@Model.CustomerName" />
<button type="button" onclick="SubmitFormForFileDownload('MyPageController','CreateFileDownload','DownloadFile');">
Export
</button>
</form>
</div>
不要拘泥于上面的格式,它只是像 ASP.NET Core MVC 一样使用模型的表单。我只是手写了它作为示例。
目标是提交模型和对下载文件时使用的表单的更改。
控制器:
[HttpPost]
[Route("MyPageController/CreateFileDownload")]
public async Task <ActionResult> CreateFileDownload(MyPagesViewModelmodel)
{
// Code to generate a file and store it on the server temporarily. Generating a file name in the process ...
// Here I generate an excel file and save it to the server.
FileInfo fi = new FileInfo(fullSavePath);
return this.Ok(fi.Name);
}
public ActionResult DownloadFile(string fileName)
{
// Note you may need to add an argument for fileType if you have various file types.
// This is an example for excel.
string fileType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
string fullSavePath = Path.Combine(...your save directory path..., fileName);
// load the file into a memory stream so I can delete it after.
MemoryStream stream = new MemoryStream(System.IO.File.ReadAllBytes(fullSavePath));
// delete the file to avoid retention issues.
System.IO.File.Delete(fullSavePath);
return File(stream, fileType, fileName);
}
Javascript 将它们整合在一起 - 需要 jQuery:
function SubmitFormForFileDownload(controllerName, generateFileAsyncActionName, fileDownloadActionName) {
let formData = $(document.querySelector("form")).serialize();
$.ajax({
type: 'POST',
url: '/' + controllerName + '/' + generateFileAsyncActionName,
contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
data: formData,
success: function (fileNameResult) {
console.log('successful file generation');
window.location.href = '/' + controllerName + '/' + fileDownloadActionName + '?fileName=' + fileNameResult;
},
error: function () {
alert('unable to download the requested file.');
console.log('unable to download the requested file.');
}
});
}
因此,根据@browsermator的建议,一个更简单的解决方案是将按钮更改为“提交”类型按钮,向按钮添加asp-controller和asp-action,然后让操作仅返回文件。 容易多了。 谢谢@browsemator!
查看 - 只是这里的按钮...
<button type="submit" asp-controller="MyPageController" asp-action="DownloadFile">
Download
</button>
控制器
[HttpPost]
[Route("MyPageController/DownloadFile")]
public ActionResult DownloadFile(string fileName)
{
// This is an example for excel.
string fileType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
MemoryStream stream = new MemoryStream();
... Load your memory stream...
//for me and how I had to load the memory stream,
//i needed to reset the stream to position 0.
stream.Position = 0;
//return the File object. I had no idea the post wouldn't reload the page.
return File(stream, fileType, fileName);
}