Asp.net 更新局部视图并下载文件

Asp.net update a partial view and download a file

我有一个网站,其中包含下载列表和已下载文件的历史记录列表。 当我单击一个时,我希望开始下载所选文件并将新项目添加到历史记录中。 目前下载有效:

    public async Task<ActionResult> DownloadSelection(int selectionId, DownloadFormat format)
    {
        var selection = databaseSelectionService.GetById(selectionId);

        string fileName = selection.Name + FileNamingHelper.GetFileExtensionByFormat(format);
        var fileBytes = await downloadManager.ExecuteSelection(selection, applicationUserManager.FindById(User.Identity.GetUserId()), format);
        return File(fileBytes, MediaTypeNames.Application.Octet, fileName);
    }

我通过 HTML.ActionLink:

调用它
@Html.ActionLink(Strings.ExcelLabel, "DownloadSelection", "Home", new { selectionId = selection.Id, format = DownloadFormat.Excel }, null)

现在我的问题是,要刷新历史记录,我必须 return 部分视图。但是因为我已经 return 一个文件作为 ActionResult,所以我也不能 return 部分视图。

我尝试了一种使用 Ajax.ActionLink 并为 OnSuccess 添加 AjaxOption 的方法,以便在下载成功后调用第二个控制器 return 局部视图。但不知何故,我的 javascript 函数从未被调用过。

@section scripts
{
    function testFunction()
    {
        alert("huhu");
    }
}

@Ajax.ActionLink(Strings.CsvLabel, "DownloadSelection", "Home", new { selectionId = selection.Id, format = DownloadFormat.CSV }, new AjaxOptions{OnSuccess = "testFunction" })

解决这个问题的好方法是什么?

查看:

@{
    ViewBag.Title = Strings.SelectionsTitle;
}

<h2>@ViewBag.Title</h2>

@if (Model.AssignedDatabaseSelections.Any())
{
    <table>
        <tr>
            <th>Abfrage</th>
            <th style="text-align:right">Download</th>
        </tr>
        @foreach (var selection in Model.AssignedDatabaseSelections)
        {
            <tr>
                <td>@selection.DisplayName</td>
                <td style="text-align:right">
                   @Ajax.ActionLink(Strings.CsvLabel, "DownloadSelection", "Home", new { selectionId = selection.Id, format = DownloadFormat.CSV }, new AjaxOptions{OnSuccess = "testFunction" })  |
                   @Ajax.ActionLink(Strings.ExcelLabel, "DownloadSelection", "Home", new { selectionId = selection.Id, format = DownloadFormat.Excel}, new AjaxOptions{OnSuccess = "testFunction" })
                </td>
            </tr>
        }
    </table>
}
else
{
    <div>
        @Strings.NoSelectionsPlaceholder
    </div>
}

<h2>@Strings.DownloadHistoryTitle</h2>

@if (Model.DownloadRecords.Any())
{
    <table>
        <tr>
            <th>Abfrage</th>
            <th>Zeitraum von</th>
            <th>Zeitraum bis</th>
            <th style="text-align:right">Download</th>
        </tr>
        @foreach (var downloadRecord in Model.DownloadRecords)
        {
            <tr>
                <td>@downloadRecord.Selection.DisplayName</td>
                <td>@downloadRecord.TimeRangeStart.ToString("d")</td>
                <td>@downloadRecord.TimeRangeEnd.ToString("d")</td>
                <td style="text-align:right">
                    @Html.ActionLink(Strings.CsvLabel, "RedownloadRecord", "Home", new {recordId = downloadRecord.Id, format = DownloadFormat.CSV}, null)
                    |
                    @Html.ActionLink(Strings.ExcelLabel, "RedownloadRecord", "Home", new {recordId = downloadRecord.Id, format = DownloadFormat.Excel}, null)
                </td>
            </tr>
        }
    </table>
}
else
{
    <div>
        @Strings.NoDownloadsPlaceholder
    </div>
}

编辑:添加了整个视图代码

您不能 return 通过 ajax 调用下载文件,因此使用 @Ajax.ActionLink() 不是 suitable。相反,在第一个 table 中处理您的链接点击并 ajax 调用更新数据库中的记录(即指示其已下载),并在成功回调中更新第二个table,并使用location.href下载文件。添加一个id属性来区分tables

<table id="assigned">
    <thead> ... add table headings ... </thead>
    <tbody>
        @foreach (var selection in Model.AssignedDatabaseSelections)
        {
            <tr>
                <td>@selection.DisplayName</td>
                <td>
                    @Html.ActionLink(Strings.CsvLabel, "DownloadSelection", "Home", new { selectionId = selection.Id, format = DownloadFormat.CSV }, null)
                    ....
                </td>
            </td>
        </tr>
    }
</table>
<div id="history">
    <table>
        <thead> ... add table headings ... </thead>
        <tbody>
            @foreach (var downloadRecord in Model.DownloadRecords)
            {
                <tr>
                    <td>@downloadRecord.Selection.DisplayName</td>
                    ....
                </tr>
            }
        </tbody>
    </table>
</div>

并在第一个 table 中添加一个脚本来处理链接的点击事件,进行 ajax 调用以更新数据库中的记录,并在其成功回调中更新第二个table,终于下载文件了。

$('#assigned').on('click', 'a', function(e) {
    e.preventDefault(); // cancel default redirect
    var downloadUrl = $(this).attr('href');
    var id = $(this).data('id');
    var row = $(this).closest('tr');
    var url = '@Url.Action("UpdateHistory")';
    $.post(url, { id: id }, function(response){
        $('#history').html(response); // update the table
        location.href = downloadUrl; // download file
    });
});

UpdateHistory方法所在

[HttpPost]
public PartialViewResult UpdateHistory(int id)
{
    // Update the database record to set the flag its been downloaded
    var model = ... // Generate a collection of the records used to display in the History table
    return PartialView("_History", model);
}

_History.cshtml 是在您的主视图中生成第二个 table 的局部视图。