【问题标题】:ASP.NET MVC - Response.Clear() in a View not working as expected after upgrade to .NET 4.0ASP.NET MVC - 升级到 .NET 4.0 后,视图中的 Response.Clear() 无法按预期工作
【发布时间】:2013-05-24 21:09:31
【问题描述】:

我刚刚将一个 ASP.NET 项目从 .NET 2.0 升级到 4.0。仍在使用 MVC 2。一些发回 .csv 文件的功能(奇怪地)被写成视图。然后,在 MainContentPlaceHolder 部分,代码丢弃了 Master 中的所有内容:

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/MyMaster" Inherits="System.Web.Mvc.ViewPage<MyViewModel>" %>

<%
    HttpContext context = HttpContext.Current;
    context.Response.Clear();
    context.Response.Write(Html.CompletionByTemplateExport((CompletionByTemplateExport)ViewData["report"]));
    context.Response.ContentType = "text/csv";
    context.Response.AppendHeader("Content-Disposition", "attachment; filename=CompletionByTemplateReport.csv");
    context.Response.End();
 %>

升级到 .NET 4.0 后,此解决方法不再起作用:.csv 文件包含母版页输出的所有 html 内容。

在升级到 .NET 4.0 时,处理请求和响应的方式发生了哪些变化?有没有办法让它以旧方式运行,以便 response.Clear() 和 Response.End() 像以前一样工作?在重写 .csv 下载功能之前,我正在寻找一个短期解决方案。

【问题讨论】:

    标签: asp.net asp.net-mvc


    【解决方案1】:

    我不完全确定如何,但似乎页面生命周期在 .NET 2.0 和 .NET 4.0 之间略有变化。我能够复制问题。

    我假设您的视图如下所示:

    <%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/MyMaster" Inherits="System.Web.Mvc.ViewPage<MyViewModel>" %>
    
    <asp:Content Id="MainContent1" ContentPlaceHolderID="MainContent">
    <%
        HttpContext context = HttpContext.Current;
        context.Response.Clear();
        context.Response.Write(Html.CompletionByTemplateExport((CompletionByTemplateExport)ViewData["report"]));
        context.Response.ContentType = "text/csv";
        context.Response.AppendHeader("Content-Disposition", "attachment; filename=CompletionByTemplateReport.csv");
        context.Response.End();
     %>
    </asp:Content>
    

    不幸的是,我相信你必须这样做:

    <%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/MyMaster" Inherits="System.Web.Mvc.ViewPage<MyViewModel>" %>
    
    <script runat="server">
    void Page_Load(object sender, EventArgs args) {
        HttpContext context = HttpContext.Current;
        context.Response.Clear();
        context.Response.Write(Html.CompletionByTemplateExport((CompletionByTemplateExport)ViewData["report"]));
        context.Response.ContentType = "text/csv";
        context.Response.AppendHeader("Content-Disposition", "attachment; filename=CompletionByTemplateReport.csv");
        context.Response.End();
     }
    </script>
    

    或者(更好),将该代码移动到控制器中(因为这是 MVC):

    public class MyController : Controller
    {
        public ActionResult Index()
        {
            // This is redundant, Controllers and Views have a Response property
            // HttpContext context = HttpContext.Current;
            CompletionByTemplateExport reportData = ...;
            Response.Clear();
            Response.Write(Html.CompletionByTemplateExport(reportData));
            Response.ContentType = "text/csv";
            Response.AppendHeader("Content-Disposition", "attachment; filename=CompletionByTemplateReport.csv");
            Response.End();   
        }
    }
    

    其中任何一个都会为您提供没有母版页 HTML 的 CSV。

    【讨论】:

    • 谢谢。我最初正在寻找某种设置,这种设置可能是一种无需更改代码即可快速修复的设置。我最终做的是修改视图以简单地输出 .csv 内容,而不涉及母版页样板。当然,这应该放在控制器中是对的——这里不需要视图。但是修改视图让我可以在不停机的情况下进行更改,所以这就是我最终要做的事情。感谢您确认版本升级发生了一些变化。我找不到任何其他提及此问题的内容。
    【解决方案2】:

    我通过添加指示文件大小的标题解决了类似的问题。

    这对我来说毫无意义,但它有效。

    With Response
        .Buffer = True
        .ClearContent()
        .ClearHeaders()        
        .ContentType = "text/csv"
        .AppendHeader("content-disposition", "attachment;  filename=" & fileName)
        .AppendHeader("Content-Length", buffer.Length)
        .OutputStream.Write(buffer, 0, buffer.Length)
        .Flush()
    End With
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多