0

I have a few large, specifically formatted to the customer's request, tables with input. It looks similar to the following...

<body id="Body" class="Window" runat="server">
    <form id="Form" runat="server" defaultbutton="SubmitLinkButton">
        <!-- Markup for a the SubmitLinkButton and DropDownList -->
        <!--    to pick which Table is shown                    -->
        <asp:Table ID="Table1" runat="server">
            <asp:TableRow class="row" runat="server">
                <asp:TableCell runat="server">
                    <pre>    Some Input1    </pre>
                    <pre>___________________</pre>
                    <pre>|___<asp:Textbox ID="Textbox1" runat="server"></asp:Textbox>____|</pre>
                    <pre>|_________________|</pre>
                </asp:TableCell>
            </asp:TableRow>
        </asp:Table>
        <asp:Table ID="Table2" runat="server">
            <asp:TableRow class="row" runat="server">
                <asp:TableCell runat="server">
                    <pre>    Some Input2    </pre>
                    <pre>___________________</pre>
                    <pre>|___<asp:Textbox ID="Textbox2" runat="server"></asp:Textbox>____|</pre>
                    <pre>|_________________|</pre>
                </asp:TableCell>
            </asp:TableRow>
        </asp:Table>
    </form>
</body>

Underwhelming, right?

Only one of the four tables is visible or not depending on the selection chosen in the DropDownList. Each table has upwards of 30-40 inputs and each area with inputs is formatted uniquely. All formatted the same way (^^^like above^^^), but one may have a section with 3 inputs and lots of text or 8 inputs and little text or no inputs and just a section of text.

Hopefully all of that makes sense.

What I need to figure out is how to have the user be able to "Submit" the form via the SubmitLinkButton which will send an email that looks identical to the form they filled out to a group of email addresses setup in the SystemFramwork.config.

I've attempted to do this, using Visual Basic, with RenderControl(), but I kept getting errors saying my Textboxes needed to be inside a form with runat="server" in it, and as you can see in my code above I have that. So, I'm not sure what was going on there.

Since the form is formatted so customized, If I can't somehow render the HTML form from page to email to have them look identical, I don't know any other option than to add the markup to the email manually, which just seems like a waste of time and making redundancies in the project.

Any insight would be greatly appreciated!

I'm still currently working with a pseudo solution that looks something like this...

Public Sub SubmitLinkButton_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles SubmitLinkButton.Click
    Dim result As String = vbNull

    Dim stringWriter As New StringWriter()
    Dim htmlWriter As New HtmlTextWriter(stringWriter)

    'If the user selected something with the DropDown
    If (DDL_Selection IsNot "")
        Dim email As New MailMessage(FromConfigVar, ToConfigVar)
        email.Subject = DDL_Selection.SelectedValue & " Table"
        email.IsBodyHtml = True

        Select Case DDL_Selection
            Case "Table1"
                Try
                    htmlWriter.RenderBeginTag(HtmlTextWriterTag.Table)
                    Table1.RenderControl(htmlWriter)
                    htmlWriter.RenderEndTag()
                    htmlWriter.Flush()

                    result = stringWriter.ToString()
                Finally
                    htmlWriter.Close()
                    stringWriter.Close()
                End Try
        End Select
        mailMessage.Body = result
    Else
        'Do nothing
    End If
End Sub

Again, this solution is not working, nor do I think I'm even close to being on the right track. Just thought I'd show what I've tried.

brettwbyron
  • 95
  • 12
  • Would you be able to take a screenshot and send that? – wazz Oct 18 '17 at 20:57
  • Of which part? The error or a sample of the table? – brettwbyron Oct 18 '17 at 20:58
  • Ah, no, I mean as an answer to the problem, can you take a screenshot (and also submit the form if necessary) and send that to the people on the email list. – wazz Oct 18 '17 at 21:01
  • @wazz, the form is submitted by the user. Assume the user has no idea how to use computers because that's as close to the truth as I can get, haha! – brettwbyron Oct 19 '17 at 12:18

2 Answers2

1

If you override the Page's VerifyRenderingInServerForm Method to not perform the validation that is causing the issue you can get around this problem:

'This is in the Page's Code Behind.
Public Overrides Sub VerifyRenderingInServerForm (control As Control)
    'Do Nothing instead of raise exception.
End Sub   
NoAlias
  • 9,218
  • 2
  • 27
  • 46
  • How would this look in my code example above? Would there be any code needed in the `Sub`? – brettwbyron Oct 19 '17 at 12:22
  • No, this should just suppress that exception you were getting... "saying my Textboxes needed to be inside a form with runat="server" in it". – NoAlias Oct 19 '17 at 13:02
  • I get an error `RegisterForEventValidation can only be called during Render();` – brettwbyron Oct 19 '17 at 13:20
  • Haha this solution is getting clunkier. Check out this link for information on how to resolve that error: https://stackoverflow.com/questions/7228718/registerforeventvalidation-can-only-be-called-during-render – NoAlias Oct 19 '17 at 14:10
  • Okay. So, after adding `<%@ Page ............ EnableEventValidation="false" %>`, it works!! I am sending the entire form as an email. Though, each input is surrounded by brackets for some reason. I'm not sure why, but I made a huge step forward with your help. – brettwbyron Oct 19 '17 at 15:13
  • Do you know if/how I could send the HTML in Print view instead of Screen? – brettwbyron Oct 19 '17 at 15:33
1

I got this version working but did not get any user-input returned. This puts the html into an email; uses HtmlAgilityPack.

using HtmlAgilityPack;
etc.

protected void btnTableToEmail_Click(object sender, EventArgs e)
{
    try
    {
        StringWriter sw = new StringWriter();
        using(HtmlTextWriter writer = new HtmlTextWriter(sw))
        {
            writer.AddAttribute("runat", "server");
            writer.RenderBeginTag("form");

            writer.Write(GetTableHTML());

            writer.RenderEndTag();
        }

        SendEmail(sw);
    }
    catch(Exception)
    {
        throw;
    }
}

private string GetTableHTML()
{
    // uses HtmlAgilityPack.

    var html = new HtmlDocument();
    html.Load(Server.MapPath("~/yourpage.aspx")); // load a file
    var root = html.DocumentNode;

    var table = root.Descendants().Where(n => n.GetAttributeValue("id", "").Equals("Table1")).Single();
    return table.InnerHtml;
}

private void SendEmail(StringWriter sw)
{
    // your email routine.
    // ...
    msg.Body = sw.ToString();
}
wazz
  • 4,953
  • 5
  • 20
  • 34
  • I want to try to be as vanilla as possible in this code. So, using a third party parser (although seemingly a great parser) is not an ideal solution to this problem. – brettwbyron Oct 19 '17 at 12:20
  • Could you write this out in VB? Even if I don't use it, I'd like to try it out. I'm currently having an issue with the line `var table = root.Descendants().Where(n => n.GetAttributeValue("id", "").Equals("Table1").Single();` In my code (VB) it looks like... `Dim table = root.Descendants().Where...` and I'm getting errors using the `Where` function. – brettwbyron Oct 19 '17 at 13:09
  • I've never used VB (only VBA) so not sure. I know there's a site or two online that can convert between the two. Not sure why that one line wouldn't work. Only guess is a missing using statement (Linq?). – wazz Oct 19 '17 at 19:43