首页 > 解决方案 > 创建和发送 Smtp 附件后渲染时出现 System.Web.HttpException

问题描述

我正在为 ASP.NET 应用程序开发增强功能,该应用程序允许用户通过电子邮件将屏幕渲染的 PDF 附件发送到指定的分发。尽管发送电子邮件成功,但这似乎使应用程序感到困惑,随后的页面刷新失败并出现 HttpException:“无法使用前导 .. 退出顶级目录。” 这是刷新失败的唯一情况。

该页面遵循以下继承模式:

Webform_HS_Proforma : Webform_ProformaBase { }
Webform_ProformaBase : System.Web.UI.Page { }

我们使用的 PDF 库是SelectPdf,但这个库似乎不太可能有问题,因为我们能够正确发送附件,并且还能够成功地将 PDF 写入数据库。

Request.Url.PathAndQuery显示正确的预期路径,并且项目中没有包含“..\”的引用。这在调用之前base.Render在子类和父类中进行检查。

各个页面位于文件夹 Pages 中。移动site.master到这个位置没有帮助。

有一个Global.asax,它的存在与否不影响这个结果。

冒犯的方法似乎是ShowRender包含在Webform_ProformaBase类中,并结合了将文件附加到电子邮件的行为。我通过明智地使用评论得出了这个结论。尽管如此,ShowRender在不同的函数中工作,无一例外地将返回产品写入数据库。这里的不同之处在于我们没有将其附加到电子邮件中。

我试图ShowRenderWebform_ProformaBaseto移动Webform_HS_Proforma并得到同样的例外。

此方法执行电子邮件和附件的创建,并发送。此方法成功完成。

        protected void OnEmailResolvedInvoked(String fromAddress = null, String toAddress = null, String ccAddress = null, String msgSubject = null, String msgBody = null)
        {
            // The user control that kicks off the process by collecting the 
            // information passed in params.  Hide the panel once its job is
            // done.  Make the main page visible again.
            panelEmailCtrl.Visible = false;
            panelBody.Visible = true;

            if (toAddress is null || fromAddress is null)
            {
                return;
            }

            // Let's send this email.
            StringWriter tw = new StringWriter();
            HtmlTextWriter hw = new HtmlTextWriter(tw);

            MailMessage message = new MailMessage();
            message.IsBodyHtml = true;
            message.From = new MailAddress(fromAddress.Trim());
            message.To.Add(toAddress.Trim());

            if (ccAddress.Length > 0)
            {
                message.CC.Add(new MailAddress(ccAddress.Trim()));
            }

            message.Subject = msgSubject;

            SelectPdf.PdfDocument doc = this.ShowRender();

            // Adds the proforma PDF as an attachment to the email.
            byte[] bytes = doc.Save();

            message.Attachments.Add(new Attachment(new MemoryStream(bytes), tbProFormaName.Text + " Proforma " + DateTime.Now.ToShortDateString() + ".pdf"));

            // Close any remaining references here.
            doc?.Close();
            hw?.Close();
            tw?.Close();

            SmtpClient client = new SmtpClient();

            try
            {
                client.Send(message);
            }
            catch (SmtpException) { /* Error handling here. */ }
            catch (Exception) { /* Error handling here. */ }
        }

这就是ShowRender方法。OnEmailResolvedInvoked文档会毫无意外地传回给调用者。

        public PdfDocument ShowRender()
        {
            TextWriter preWriter = new StringWriter();
            HtmlTextWriter htmlWriter = new HtmlTextWriter(preWriter);

            this.Render(htmlWriter);

            HtmlToPdf converter = new HtmlToPdf();

            // Options for presentation.
            converter.Options.PdfPageSize = PdfPageSize.Legal;
            converter.Options.PdfPageOrientation = PdfPageOrientation.Portrait;
            converter.Options.MarginLeft = 10;
            converter.Options.MarginRight = 10;
            converter.Options.MarginTop = 20;
            converter.Options.MarginBottom = 20;

            PdfDocument doc = converter.ConvertHtmlString(preWriter.ToString(), Request.Url.AbsoluteUri);

            preWriter?.Close();
            htmlWriter?.Close();

            return doc;
        }

一旦我们成功完成此操作,页面将尝试回发。 Webform_HS_Proforma的 Render 方法是有条件的,但是这个方法转到了只调用base.Render. 异常被抛出Webform_ProformaBase

归根结底,重定向可能会导致用户丢失当前输入的任何数据。我不知所措。这似乎没有理由失败。

[HttpException (0x80004005): Cannot use a leading .. to exit above the top directory.]
   System.Web.Util.UrlPath.ReduceVirtualPath(String path) +769
   System.Web.Util.UrlPath.Reduce(String path) +82
   System.Web.Util.UrlPath.Combine(String appPath, String basepath, String relative) +299
   System.Web.UI.Control.ResolveClientUrl(String relativeUrl) +377
   System.Web.UI.HtmlControls.HtmlLink.RenderAttributes(HtmlTextWriter writer) +74
   System.Web.UI.HtmlControls.HtmlLink.Render(HtmlTextWriter writer) +41
   System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +128
   System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +287
   System.Web.UI.Control.RenderControl(HtmlTextWriter writer) +27
   System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +197
   System.Web.UI.HtmlControls.HtmlHead.RenderChildren(HtmlTextWriter writer) +21
   System.Web.UI.HtmlControls.HtmlContainerControl.Render(HtmlTextWriter writer) +32
   System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +128
   System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +287
   System.Web.UI.Control.RenderControl(HtmlTextWriter writer) +27
   System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +197
   System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) +9
   System.Web.UI.Control.Render(HtmlTextWriter writer) +10
   System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +128
   System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +287
   System.Web.UI.Control.RenderControl(HtmlTextWriter writer) +27
   System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +197
   System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) +9
   System.Web.UI.Page.Render(HtmlTextWriter writer) +30
   ProformaBuilder.Pages.WebForm_ProformaBase.Render(HtmlTextWriter writer) in C:\[Structure]\Pages\WebForm_ProformaBase.aspx.cs:290
   ProformaBuilder.Pages.WebForm_HS_Proforma.Render(HtmlTextWriter writer) in C:\[Structure]\Pages\WebForm_HS_Proforma.aspx.cs:813
   System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +128
   System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +287
   System.Web.UI.Control.RenderControl(HtmlTextWriter writer) +27
   System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +5625

标签: c#asp.net

解决方案


推荐阅读