Wednesday, February 5, 2014

Emailing an ASP.NET GridView

There are times you want to send an ASP.NET GridView along with data as an Email. Your recipient should receive it with the styles you have applied to the GridView inside your ASP.NET web page. This post is supposed to explain the way to achieve such a task.

First I will be creating an empty ASP.NET web application. I have nothing but a empty Web Form added to the application which I named as “Default”. Now in the code behind of the Web Form, I have following helper method which will return me a DataTable holding some data which I need to be shown in the GridView.
private DataTable GetData()
{
   DataTable dt = new DataTable();
   dt.Columns.AddRange(new DataColumn[2] 
   { 
       new DataColumn("Id"), new DataColumn("FullName")
   });
   dt.Rows.Add(1, "Jaliya Udagedara");
   dt.Rows.Add(2, "John Doe");
   dt.Rows.Add(3, "Jane Doe");
   return dt;
}
There is noting complex in the above method, just creating a DataTable with some columns, filling up some data and then returning the DataTable.

In the Web Form, I have the following design.
<body>
    <form id="form1" runat="server">
        <div>
            <asp:GridView ID="GridView1"
                runat="server" 
                AutoGenerateColumns="false"
                HeaderStyle-BackColor="#3d5bb8" 
                HeaderStyle-ForeColor="White"

                RowStyle-BackColor="#c6c6c6"
                lternatingRowStyle-BackColor="White"
                AlternatingRowStyle-ForeColor="#000">
                <Columns>
                    <asp:BoundField DataField="Id"
                        HeaderText="Id"
                        ItemStyle-Width="80" />
                    <asp:BoundField DataField="FullName"
                        HeaderText="Full Name"
                        ItemStyle-Width="200" />
                </Columns>
            </asp:GridView>
            <br />
            <asp:Button ID="btnSend" 
                runat="server" Text="Send" 
                OnClick="btnSend_Click" />
        </div>
    </form>
</body>
Here there is GridView inside a Form tag, I have applied some styles to keep my GridView look nicer. Now in the Page_Load event of my Web Form, I am binding the GridView to the DataTable which is received from above GetData() method. Now when I run the application, I am getting the following page.

GridView
ASP.NET GridView
Now comes the real requirement. When I click on Send button, an email should be sent with GridView with the styles applied along with the data.

To create the mail message and to send it I have the following method.
private void SendGridViaEmail(string htmlContent)
{
    MailMessage mailMessage = new MailMessage("sender@gmail.com", "receiver@gmail.com")
    {
        Subject = "Email an ASP.NET GridView",
        Body = "Emailed GridView:<hr />" + htmlContent,
        IsBodyHtml = true
    };
 
    SmtpClient smtpClient = new SmtpClient()
    {
        Host = "smtp.gmail.com",
        Port = 587,
        EnableSsl = true,
        Credentials = new NetworkCredential()
        {
            UserName = "sender@gmail.com",
            Password = "senderpassword"
        }
    };
    smtpClient.Send(mailMessage);
}
Above method accepts a string and that particular string will be sent as the body in my MailMessage. And please note here in my MailMessage, I am setting up the property IsBodyHtml to true. That’s because I am planning to retrieve the content of my GridView as a markup characters using the GridView.RenderControl Method. And that particular string will be the body of my MailMessage. After doing that, I am creating a SmtpClient to send the email through Gmail SMTP.

Now in my Send button click I have the following.
protected void btnSend_Click(object sender, EventArgs e)
{
    using (StringWriter stringWriter = new StringWriter())
    {
        using (HtmlTextWriter htmlTextWriter = new HtmlTextWriter(stringWriter))
        {
            GridView1.RenderControl(htmlTextWriter);
            SendGridViaEmail(stringWriter.ToString());
        }
    }
}
Here GridView.RenderControl Method (HtmlTextWriter) Outputs server control content to the provided HtmlTextWriter object. StringWriter is required for the HtmlTextWriter to write to. It is a buffer and everything that is written to HtmlTextWriter is written to StringWriter. Then I am passing content in StringWriter to my SendGridViaEmail() method. Here you can either use,
SendGridViaEmail(htmlTextWriter.InnerWriter.ToString());
But HtmlTextWriter.InnerWriter Property will be eventually giving you the reference to underlying writer which is the used StringWriter.

Now when I run the application and click on Send button, I am getting this nice little error message which is “Control 'GridView1' of type 'GridView' must be placed inside a form tag with runat=server. ”.

GridView
Control 'GridView1' of type 'GridView' must be placed inside a form tag with runat=server.
I am sure my control 'GridView1' is placed inside a form tag with runat=server. But the problem is when we render the control using GridView.RenderControl Method, the markup will be rendered without the form tag. You can simple avoid this error by adding the following method. This Page.VerifyRenderingInServerForm Method confirms that an HtmlForm control is rendered for the specified ASP.NET server control at run time.
public override void VerifyRenderingInServerForm(Control control)
{
   
}
Now when I build and run the application and click on Send button, I am not getting any errors, instead I am getting the desired output, an email sent with styled GirdView along with data.

Email
Resulting Email
Hope this helps. I am uploading the sample to my SkyDrive.


Happy Coding

Regards,
Jaliya

3 comments: