System.Web.HttpException on Render After Smtp Attachment Created and Sent

0

I'm working on enhancement functionality for an ASP.NET application that allows the user to send a PDF attachment of a screen render via email to a specified distribution. Although sending the email succeeds, this seems to confuse the application and the subsequent page refresh fails with an HttpException: "Cannot use a leading .. to exit above the top directory." This is the only situation in which a refresh fails.

The page follows this inheritance pattern:

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

The PDF library we're using is SelectPdf, but it seems unlikely that this library is a problem, since we're able to send the attachment correctly and also to elsewhere successfully write the PDF to a database.

Request.Url.PathAndQuery show the correct intended path and there are no references in the project that include "..\". This is checked prior to the call to base.Render in both the child-class and the parent-class.

The individual pages are located inside a folder, Pages. Moving the site.master to this location does not help.

There is a Global.asax, the presence or absence of which does not affect this outcome.

The offending method appears to be ShowRender, contained in the Webform_ProformaBase class combined with the act of attaching the file to an email. I reached this conclusion by judicious use of commenting. Nonetheless, ShowRender works in a different function without exception that writes the return-product to the database. The difference here is that we're not attaching it to an email.

I tried to move ShowRender from Webform_ProformaBase to Webform_HS_Proforma and got the same exception.

This method carries out the creation of the email and attachment, and sends it. This method completes successfully.

        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. */ }
        }

This is the ShowRender method. The document is passed back to the caller in OnEmailResolvedInvoked without incident.

        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;
        }

Once we've successfully completed this, the page will attempt to post-back. Webform_HS_Proforma's Render method is a conditional, but this method goes to a branch that only calls base.Render. The exception is thrown in Webform_ProformaBase.

At the end of the day, a redirect could cause users to lose any data currently input. I'm at a loss. There seems to be no reason why this is failing.

[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
asked on Stack Overflow Aug 16, 2019 by Kundich • edited Aug 16, 2019 by Kundich

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0