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