Исключение BinaryWrite «OutputStream недоступен при использовании пользовательского TextWriter» в MVC 2 ASP.NET 4 - PullRequest
16 голосов
/ 14 февраля 2010

У меня есть представление рендеринга потока с использованием метода BinaryWrite ответа. Все это прекрасно работало в ASP.NET 4 с использованием бета-версии 2, но в выпуске RC выдается следующее исключение:

«HttpException», «OutputStream не является доступно, когда пользовательский TextWriter используемый."

<%@ Page Title="" Language="C#" Inherits="System.Web.Mvc.ViewPage" %>
<%@ Import Namespace="System.IO" %>
<script runat="server">
protected void  Page_Load(object sender, EventArgs e)
{
    if (ViewData["Error"] == null)
    {

        Response.Buffer = true;
        Response.Clear();
        Response.ContentType = ViewData["DocType"] as string;
        Response.AddHeader("content-disposition", ViewData["Disposition"] as string);
        Response.CacheControl = "No-cache";
        MemoryStream stream = ViewData["DocAsStream"] as MemoryStream;
        Response.BinaryWrite(stream.ToArray());
        Response.Flush();
        Response.Close();
    }
}   
</script>


</script>

Представление генерируется из перенаправления на стороне клиента (вызов местоположения jquery replace на предыдущей странице с использованием помощника Url.Action для отображения ссылки, конечно) Это все в фрейме.

У кого-нибудь есть идея, почему это происходит?

Ответы [ 3 ]

17 голосов
/ 15 февраля 2010

Когда ViewPage начинает выполняться, он предполагает определенные вещи относительно оставшейся части запроса. Особенность, которая сбивает вас с толку, заключается в том, что ViewPage предполагает, что оставшаяся часть запроса будет обычным HTML или каким-либо другим текстовым ответом, поэтому он переключает TextWriter ответа со своим собственным средством записи.

В вашем случае вы должны создать новый производный от ActionResult класс, метод ExecuteResult которого инкапсулирует логику в вашем методе Page_Load. Ваш метод действия должен возвращать экземпляр вашего пользовательского класса, и вызывающий будет запускать метод ExecuteResult в соответствующее время. Это полностью обходит механизмы представления, что предотвращает ошибку, с которой вы работаете, и дает небольшое повышение производительности.

11 голосов
/ 26 февраля 2010

Я сделал ответ Леви. Это на самом деле очень просто. Мой код записывает в ответ изображение, которое ранее получалось из файловой системы после различных проверок.

public class BookImageResult : ActionResult
{
    private readonly GraphicReport graphicReport;

    public BookImageResult(GraphicReport graphicReport)
    {
        this.graphicReport = graphicReport;
    }

    public override void ExecuteResult(ControllerContext context)
    {
        var response = context.RequestContext.HttpContext.Response;
        response.Clear();
        response.ContentType = graphicReport.ContentType;
        response.BinaryWrite(graphicReport.Image);
        response.End();
    }
}

Строка в конце контроллера выглядит так:

return new BookImageResult(graphicReport);

Кто-то помечает ответ Леви как ответ!

2 голосов
/ 15 сентября 2011

Еще один способ сделать что-то подобное - использовать встроенный File ActionResult:

var bytes = GetPdfBytes("Performance Report", htmlString);
return File(bytes, "binary/octet-stream", "Performance Report.pdf");
...