【问题标题】:Model on the razor view is not getting updated on form submit剃刀视图上的模型未在表单提交时更新
【发布时间】:2023-11-13 22:03:01
【问题描述】:
  public ActionResult Index(int id, string name)
  {
        var model = new ITViewModel
        {
           Packages = _Repository.GetDeployedPackages(id)
        };
        return View(model);
  }

 [HttpPost]
 public ActionResult GeneratePackage(ITViewModel model)
    {
    _Repository.SavePackage(model);

    //Generate Zip file Package
    //Get file template  in archiveStream
            Response.Clear();
            Response.ContentType = "application/zip";
            Response.AppendHeader("content-disposition", "attachment; filename="testzipPackage");
            Response.CacheControl = "Private";
            Response.Cache.SetExpires(DateTime.Now.AddMinutes(3));
            Response.Buffer = true;
            var writeBuffer = new byte[4096];

           var count = archiveStream.Read(writeBuffer, 0, writeBuffer.Length);
            while (count > 0)
            {
                Response.OutputStream.Write(writeBuffer, 0, count);
                count = archiveStream.Read(writeBuffer, 0, writeBuffer.Length);

           }
    model.Packages = _Repository.GetDeployedPackages(model.id) //get the correct package list with the one tht we just saved on this ActionResult

    return View("Index",model);
    }

    //Index
    @model  ITViewModel
    @using (Html.BeginForm("GeneratePackage", "Integration", FormMethod.Post)
{
    //some input form 
}

<table>
 @foreach (var package in Model.Packages)
            {
<tr>
<td>
        @package.Name
</td>
</tr>
}
</table>

我能够正确下载 zip 文件。在调试器中,我还看到了带有新添加元素的包列表。但是帖子上的视图没有刷新。我的意思是 Index 上的表格不会用新的模型元素刷新。甚至 document.ready 也没有被调用一次 return View("Index",model) 被触发。

 I have tried ModelState.Clear(). It didn't work.

【问题讨论】:

  • 你不能让一个 HTTP 响应同时做两件事。内容是text/html(用于查看)或application/zip(用于下载),但不能两者兼有。您将需要执行其他操作,例如返回视图,然后通过 javascript 开始下载。
  • @PaulAbbott wat 是解决这个问题的方法吗?我需要用户下载 zip。但我也希望他们看到更新后的列表。我可以在压缩 zip 后强制刷新页面吗
  • 解决方法是返回视图,然后通过 javascript 开始下载。您将需要进行第二个控制器操作来下载文件并通过 javascript 调用它。你不能先下载再刷新页面,因为下载只是一个文件传输,下载完成后没有办法包含“指令”来做任何其他事情。

标签: c# asp.net asp.net-mvc httpresponse


【解决方案1】:

您不能从单个 HTTP 请求返回两个不同的响应。

你正在写回复:

Response.OutputStream.Write(writeBuffer, 0, count);

您之后所做的任何事情都不会由服务器或客户端处理。

您的网络浏览器正在下载文件,而不仅仅是停留在同一页面上。这很正常。

如果您想刷新页面,您可能需要使用 JavaScript 客户端来完成。

这是一个使用 jQuery 的小例子,假设 myForm 作为您的表单 ID:

$('#myForm').submit(function() {
    setTimeout(function () {
        window.location.reload();
    }, 1000); // use a timeout as big as you need
});

您可能还需要将target="_blank" 添加到您的表单标签中。

【讨论】:

  • 我尝试在文档中准备好,但它只是没有在提交时调用索引页面上的任何脚本。如何在文档下载时强制刷新页面?
  • 在表单提交时附加刷新逻辑,like this OR 反转逻辑并返回包含要下载文件的链接的视图(如 Paul Abbott 建议的那样)。
  • 你建议 $('#myForm').submit(function() { location.reload(); } 绑定提交事件吗?很抱歉打扰你,你能用一个更新你的答案吗?小JS代码?
  • 感谢 Federico ..不确定是否有更好的方法,但此解决方案目前有效。