Fredrik Normén's Blog - NSQUARED²
Any fool can write code that a computer can understand. Good programmers write code that humans can understand.

Microsoft Most Valuable Professional
     .Net Framework - ASP.Net - Architecture - Development
NOTE: This list of posts will only list the 15 latest posts, to see the rest, select from the Archives located in the menu to the left. The RSS will only list the 10 lastest posts.
Send an e-mail with the content of a GridView

Category:  ASP.Net 2.0

I have seen several questions lately on the ASP.Net Forum about how to expert and send an e-mail with the content of a GridView in ASP.Net 2.0. So I decided to post a short post about how you can make it possible.

 

To get the content (HTML format) from a control you can use the control’s RenderControl method. This method takes an HtmlTextWriter as an argument. The following example shows how you can simply get the content from a GridView control:

 

StringWriter stringWriterTmp = new StringWriter();

       

HtmlTextWriter htmlWriter = new HtmlTextWriter(stringWriterTmp);

GridView1.RenderControl(htmlWriter);

 

string htmlContent = stringWriterTmp.ToString();

 

When you use the HtmlTextWriter you need to pass a TextWriter as an argument to the constructor. This is done by using the StringWriter class (the StringWriter inherits the TextWriter class). The RenderControl method of the GridView control will write down the control’s content to the HtmlTextWriter you pass as an argument, and you can then use the StringWriter to get the HTML content.

 

If you add the code above for a Click event of a button control, you will get an exception about the GridView need to be placed inside of a FORM element (HtmlForm) with the runat=”server” attributes set or something similar. This is because the Page’s VerifyRenderingInServerForm method will be called to verify if the control is rendered inside of the FORM element. In this case you render it manually and it will be handling outside of a FORM, and that is the reason why you get the exception. To handle it, you can for example create our own custom Page and override the VerifyRenderingInServerForm method and make sure it will not perform the verification of your GridView control. You also need to inherit our custom Page. Here is an example:

 

public partial class Default : MyPage

{

    protected void Page_Load(object sender, EventArgs e)

    {

    }

 

    protected void Button1_Click(object sender, EventArgs e)

    {

          StringWriter stringWriterTmp = new StringWriter();

        

          HtmlTextWriter htmlWriter = new HtmlTextWriter(stringWriterTmp);

          GridView1.RenderControl(htmlWriter);

 

          string htmlContent = stringWriterTmp.ToString();

 

          ...

 

    }

}

 

 

public class MyPage : Page

{

    public override void VerifyRenderingInServerForm(Control control)

    {

        GridView grid = control as GridView;

 

        if (grid != null && grid.ID == "GridView1")

            return;

        else

            base.VerifyRenderingInServerForm(control);

    }

}

 

Note: GridView1 in the code above is the ID set to the GridView’s ID attribute in the default.aspx page.

 

As long as there are no controls in the GridView that can do a postback, the code above will work fine. But if you have controls that do a postback, like columns with sorting or paging enable etc. You will get an exception that the controls aren’t rendered inside of an HtmlForm.

 

To solve that issue, you can for example hide all controls that do a postback, or create a new instance of the HtmlForm and add it to a new instance of the Page object. Here is an example where the custom Page is used to by pass the call to the VerifyRenderingInServerForm if the control is a GridView with a specific id:

 

protected void Button1_Click(object sender, EventArgs e)

{

   MyPage tmpPage = new MyPage();

   HtmlForm form = new HtmlForm();

 

   form.Controls.Add(GridView1);

   tmpPage.Controls.Add(form);

       

   StringWriter sw = new StringWriter();

       

   HtmlTextWriter htmlWriter = new HtmlTextWriter(sw);

   form.Controls[0].RenderControl(htmlWriter);

 

   string htmlContent = sw.ToString();

}

 

The problem with this solution is that the GridView will not be rendered to the “main” page. To solve that you can for example first get the position of where the GridView is added to the main page (can use the HtmlForm’s IndexOf property), and then call the RenderControl method, and after that add the GridView to the main Page HtmlForm at the same position by using the AddAt method of the HtmlForm’s Controls property. But this can mess up the ViewState so be careful if you use that solution. Another solution would be to dynamically create and add a new copy of your GridView to the new instance of the Page object. If you don’t want to dynamically create new GridView, you can for example when you have sent the e-mail use Response.Redirect to redirect back the page and show it from its original state. You can of course also redirect to another page that show a message that the mail have been sent etc. There are several solutions to solve it, but at least, now you know how to get the content out from the GridView.

 

To send the content through an e-mail we can use the SmtpClient class, here is an example:

 

using (MailMessage mailMessage = new MailMessage(from, sendTo))

{

   mailMessage.Subject = “My Exported GridView”;

   mailMessage.Body = htmlContent;

   mailMessage.IsBodyHtml = true;

 

   SmtpClient smtpClient = new SmtpClient(myHost);

   smtpClient.Send(mailMessage);

}

 

I should not use the RenderControl at all if I need to send the content through an e-mail or export it to other files. Instead I should create a business object that would get the data from the data source and export it to my own defined XML format, and use XSLT to transform the XML into a HTML or other formats.

Computers Blogs - Blog Top SitesBloggtoppen.se
Posted: Tuesday, April 03, 2007 - 11:33 GMT+1    Print     E-mail    Comments (8)
   fredrik.nsquared2.com - 2007