Рендеринг представления в строку с последующим перенаправлением приводит к исключению

StackOverflow https://stackoverflow.com/questions/1149068

Вопрос

Итак, вот в чем проблема:Я создаю электронные письма для отправки моим приложением, преобразуя полноэкранные страницы в строки и отправляя их.Это работает без каких-либо проблем, если после этого я не перенаправляюсь на другой URL-адрес сайта.Всякий раз, когда я пытаюсь, я получаю «System.Web.HttpException:Невозможно перенаправить после отправки HTTP-заголовков».

Я считаю, что проблема возникает из-за того, что я повторно использую контекст действия контроллера, откуда поступает вызов для создания электронного письма.Точнее, HttpResponse из контекста.К сожалению, я не могу создать новый HttpResponse, который использует HttpWriter, потому что конструктор этого класса недоступен, а использование любого другого класса, производного от TextWriter, приводит к тому, что метод response.Flush() сам генерирует исключение.

Есть ли у кого-нибудь решение для этого?

    public static string RenderViewToString(
        ControllerContext controllerContext,
        string viewPath,
        string masterPath,
        ViewDataDictionary viewData,
        TempDataDictionary tempData)
    {
        Stream filter = null;
        ViewPage viewPage = new ViewPage();

        //Right, create our view
        viewPage.ViewContext = new ViewContext(controllerContext,
            new WebFormView(viewPath, masterPath), viewData, tempData);

        //Get the response context, flush it and get the response filter.
        var response = viewPage.ViewContext.HttpContext.Response;
        //var response = new HttpResponseWrapper(new HttpResponse
        //    (**TextWriter Goes Here**));
        response.Flush();
        var oldFilter = response.Filter;

        try
        {
            //Put a new filter into the response
            filter = new MemoryStream();
            response.Filter = filter;

            //Now render the view into the memorystream and flush the response
            viewPage.ViewContext.View.Render(viewPage.ViewContext,
                viewPage.ViewContext.HttpContext.Response.Output);
            response.Flush();

            //Now read the rendered view.
            filter.Position = 0;
            var reader = new StreamReader(filter, response.ContentEncoding);
            return reader.ReadToEnd();
        }
        finally
        {
            //Clean up.
            if (filter != null)
                filter.Dispose();

            //Now replace the response filter
            response.Filter = oldFilter;
        }
    }
Это было полезно?

Решение

Вам придется инициировать новый запрос.Бит, ты действительно хочешь отправлять электронные письма таким образом синхронно?Если почтовый сервер не работает, пользователь может долго ждать.

Я всегда помещаю электронные письма в автономную очередь и отправляю их по почте.Вы можете рассмотреть возможность использования для этого механизма шаблонов Spark.

Еще один подход — не перенаправлять, а записать страницу с мета-тегом перенаправления.

Другие советы

Вот альтернативный метод рендеринга представления в строку, который никогда не приводит к выводу данных в ответ (поэтому он должен избежать вашей проблемы): http://craftycodeblog.com/2010/05/15/asp-net-mvc-render-partial-view-to-string/

Чтобы отобразить обычное представление вместо частичного, вам необходимо изменить «ViewEngines.Engines.FindPartialView» на «ViewEngines.Engines.FindView».

Взгляните на MVC Contrib EmailTemplateService, который делает именно то, что вам нужно.

http://mvccontrib.googlecode.com/svn/trunk/src/MVCContrib/Services/EmailTemplateService.cs

Извините, Крис, не совсем понимаю, о чем я думал, но я явно не читал вопрос.Хотя я не могу подсказать вам, как обойти эту проблему, я могу сказать вам, почему вы получаете ошибку: HttpResponse.Flush() отправляет заголовки перед тем, как сбросить содержимое в ваш фильтр.Это устанавливает флаг внутри ответа, поэтому при попытке перенаправления вы получаете исключение.

Используя рефлектор для просмотра кода внутри Flush, я не вижу никакого чистого способа обойти это без большого количества отражений и других гадостей.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top