ASP.NET Core 8.0 MVC:根据页面模型和表单下载文件

问题描述 投票:0回答:1

我到处都找到了关于如何实现这一目标的各种信息,但我没有找到任何将它们组合在一起的东西。

我有两个问题:

  1. 有更好的方法来实现这一点吗?我不想走上 HTTP

    GET
    请求的模型绑定之路。我有很多字段,我不想遍历所有内容并为每个字段和我需要提供给
    [BindProperty(Name = "whatever", SupportsGet = true)]
    的每个属性添加一堆
    GET
    属性。

  2. 我如何最好地处理 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.');
        }

    });
}
.net-core download webforms asp.net-core-mvc
1个回答
0
投票

因此,根据@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);
}
© www.soinside.com 2019 - 2024. All rights reserved.