我正在编写自定义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
答案 0 :(得分:1)
ASP.NET管道管理响应对象的生命周期。如果您突然关闭流或结束响应,则下游组件在尝试写入时将失败。
如果要强制系统结束响应,则应调用HttpApplication.CompleteRequest()
。它将绕过ASP.NET管道中的其余事件,因此它不是没有潜在的不良副作用,但它是推荐的方法。
可以找到更多信息here。
答案 1 :(得分: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();
}
Stream由Serializer.Serialize
写入其中,此方法还返回在输出流中写入的内容的长度。