【问题标题】:HttpWebResponse output stream doesn't closeHttpWebResponse 输出流未关闭
【发布时间】:2012-02-07 17:08:19
【问题描述】:

我正在编写自定义 ActionFilterAttribute 并尝试将一些数据直接写入 ASP.NET MVC 3 中的输出流。我正在编写的数据就是我需要响应的所有数据,但是在写入之后我的数据后的额外数据 - 渲染视图。我正在尝试关闭OutputStream,但它仍然可以进行写作。如何关闭此流以进行写入或忽略 HTML 呈现?

public override void OnActionExecuted(ActionExecutedContext filterContext)
{
    var request = filterContext.RequestContext.HttpContext.Request;
    var acceptTypes = request.AcceptTypes ?? new string[] {};
    var response = filterContext.HttpContext.Response;

    if (acceptTypes.Contains("application/json"))
    {
        response.ContentType = "application/json";
        Serializer.Serialize(data, response.ContentType, response.OutputStream);
    }
    else if (acceptTypes.Contains("text/xml"))
    {
        response.ContentType = "text/xml";
        Serializer.Serialize(data, response.ContentType, response.OutputStream);
    }
    response.OutputStream.Close();
}  

UPD
例如我的数据是{"Total": 42, "Now": 9000}
而我的看法是这样的

<div>
    <span>The data that shouldn't be here</span>
</div>

作为回应,我得到了

{"Total": 42, "Now": 9000}
<div>
    <span>The data that shouldn't be here</span>
</div>

如您所见,它不是有效的 JSON。我的目标是只发送 JSON 或 XML

【问题讨论】:

  • 尝试关闭响应而不是输出流
  • @DenisPostu 当我关闭响应时,请求无法完成
  • 也许您可以描述您要完成的工作以及您在响应中得到的具体内容是不需要的?
  • @ProgrammingHero 我已经更新了问题
  • 好的,您正在尝试发送 JSON 响应。您是否有理由不能简单地从操作中返回 JsonResult

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


【解决方案1】:

经过大量努力,我找到了适合我要求的决定。这是最重要的问题。我所需要的只是在关闭它之前刷新响应。但在这种情况下,Content-Length HTTP 标头丢失,内容的长度直接写入响应正文。所以我们只需要在刷新响应之前手动设置这个头。

public override void OnActionExecuted(ActionExecutedContext filterContext)
{
    var request = filterContext.RequestContext.HttpContext.Request;
    var acceptTypes = request.AcceptTypes ?? new string[] {};
    var response = filterContext.HttpContext.Response;

    if (acceptTypes.Contains("application/json"))
    {
        WriteToResponse(filterContext, data, response, "application/json");
    }
    else if (acceptTypes.Contains("text/xml"))
    {
        WriteToResponse(filterContext, data, response, "text/xml");
    }
}

private void WriteToResponse(ActionExecutedContext filterContext, object data, HttpResponseBase response, String contentType)
{
    response.ClearContent();
        response.ContentType = contentType;
        var length = Serializer.Serialize(data, response.ContentType, response.OutputStream);
        response.AddHeader("Content-Length", length.ToString());
        response.Flush();
        response.Close();
}

流由Serializer.Serialize写入其中,该方法还返回写入输出流的内容长度。

【讨论】:

    【解决方案2】:

    ASP.NET 管道管理响应对象的生命周期。如果您突然关闭流或结束响应,则下游组件在尝试写入时将失败。

    如果你想强制系统结束响应,你应该调用HttpApplication.CompleteRequest()。它将绕过 ASP.NET 管道中的其余事件,因此它并非没有潜在的不良副作用,但这是推荐的方法。

    更多信息可以在here找到。

    【讨论】:

    • @Programming_Hero 非常感谢,但这并不是我所需要的。它只是继续在管道中执行常规操作,我得到相同的结果
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-06-18
    • 1970-01-01
    • 2021-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多