【问题标题】:Render view to string followed by redirect results in exception将视图呈现为字符串,然后重定向导致异常
【发布时间】:2010-11-12 01:17:35
【问题描述】:

所以问题来了:我正在构建要由我的应用程序发送的电子邮件,方法是将完整视图页面呈现为字符串并发送它们。只要我之后不重定向到站点上的另一个 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;
        }
    }

【问题讨论】:

    标签: asp.net-mvc redirecttoaction httpexception


    【解决方案1】:

    您必须发起一个新请求。 比特,你真的要这样同步发送邮件吗?如果邮件服务器出现故障,用户可能会等待很长时间。

    我总是将电子邮件放在离线队列中并让服务人员邮寄它们。您可以考虑为此使用 Spark 模板引擎。

    另一种方法是不重定向,而是用元重定向标签写出页面

    【讨论】:

    • 我想使用 WebForms 引擎自己构建电子邮件正文。 Spark 看起来有点整洁,但我仍然更喜欢始终使用 WebForms 的想法。顺便说一句,通过新请求,我假设 HttpServerUtility.Execute 很好?至于同步发送,不一定是这样,全看SmtpClient的设置不是吗?因为我可以让它将邮件转储到一个文件夹中以便以后发送,所以这不是问题。
    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

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

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

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

      使用反射器查看 Flush 中的代码,如果没有大量反射和其他麻烦,我看不出有任何干净的方法可以解决这个问题。

      【讨论】:

      • 不,会有同样的问题。 EmailTemplateService.RenderMessage() 实际上与我已经使用的代码相同,除了使用 MailMessage 而不是字符串。
      • 我知道是对 Flush 的调用导致了它。 Phil 说得对,唯一的办法就是创建一个全新的请求。
      猜你喜欢
      • 1970-01-01
      • 2010-11-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-19
      • 1970-01-01
      • 1970-01-01
      • 2017-05-07
      相关资源
      最近更新 更多