将视图渲染为字符串,然后重定向导致异常

时间:2009-07-19 01:59:47

标签: asp.net-mvc redirecttoaction httpexception

所以这就是问题:我正在构建通过我的应用程序发送的电子邮件,将完整的查看页面呈现为字符串并发送它们。只要我之后没有重定向到网站上的其他URL,这没有任何问题。每当我尝试时,我都会收到“System.Web.HttpException:在发送HTTP标头后无法重定向。”

我认为问题来自于我正在重复使用控制器操作的上下文,其中创建电子邮件的调用来自。更具体地说,来自上下文的HttpResponse。不幸的是,我无法创建一个使用HttpWriter的新HttpResponse,因为该类的构造函数是无法访问的,并且使用从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;
        }
    }

3 个答案:

答案 0 :(得分:2)

您必须发起新请求。 有没有,你真的想以这种方式同步发送电子邮件吗?如果邮件服务器关闭,用户可能会等待很长时间。

我总是将电子邮件放在脱机队列中,并将服务邮件发送给他们。您可以考虑使用Spark模板引擎。

另一种方法是不重定向,但写出带有元重定向标记的页面

答案 1 :(得分:2)

这是一种将视图呈现给字符串的替代方法,该字符串永远不会导致数据输出到响应(因此它应该避免您的问题):http://craftycodeblog.com/2010/05/15/asp-net-mvc-render-partial-view-to-string/

要渲染常规视图而不是局部视图,您需要将“ViewEngines.Engines.FindPartialView”更改为“ViewEngines.Engines.FindView”。

答案 2 :(得分:0)

查看MVC Contrib EmailTemplateService,它完全符合您的要求。

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

对不起克里斯,不太清楚我在想什么,但我显然没有看过这个问题。虽然我无法解决这个问题,但我可以告诉您为什么会收到错误 - HttpResponse.Flush()会在将内容刷新到您的过滤器之前发送标头。这会在响应中设置一个标志,以便在您尝试重定向时获得异常。

使用反射器来查看Flush中的代码,我看不到任何干净的方法来解决这个问题而没有太多的反思和其他的肮脏。