2012-01-11 3 views
1

Я пишу пользовательский ActionFilterAttribute и пытаюсь записать некоторые данные непосредственно в поток вывода в ASP.NET MVC 3. Данные, которые я пишу, это все, что мне нужно в ответ, но после записи есть дополнительные данные после просмотра данных. Я пытаюсь закрыть OutputStream, но он все еще остается доступным для написания. Как закрыть этот поток для записи или игнорировать последующую визуализацию HTML?Выходной поток HttpWebResponse не закрывается

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

Попробуйте закрыть ответ, а не OutputStream – DenisPostu

+0

@DenisPostu, когда я закрываю ответ, запрос не может быть завершен –

+0

Возможно, вы можете описать, что вы пытаетесь выполнить, и что конкретно вы получаете в отклике, который нежелателен? –

ответ

0

После большого количества усилий я нашел решение, соответствующее моим требованиям. Это было на вершине проблемы. Все, что мне нужно, это очистить ответ до его закрытия. Но в этом случае пропущен 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 и этот метод также возвращает длину содержимого, написанной в выходном потоке.

1

Конвейер ASP.NET управляет жизненным циклом объекта ответа. Если вы должны внезапно закрыть поток или завершить ответ, компоненты, расположенные ниже по течению, потерпят неудачу, когда они попытаются написать.

Если вы хотите, чтобы система завершила отклик, вы должны позвонить HttpApplication.CompleteRequest(). Он будет обходить остальные события в конвейере ASP.NET, поэтому он не лишен потенциально нежелательных побочных эффектов, но это рекомендуемый подход.

Более подробную информацию можно найти here.

+0

@Programming_Hero много, но это не совсем то, что мне нужно. Он просто продолжает делать обычные действия в конвейере, и я получаю тот же результат –

Смежные вопросы