Dot Net Tricks

Articles about .NET, ASP.NET, C#, Object Oriented Programming and Agile Methodologies
Welcome to Dot Net Tricks Sign in | Join | Help
in Search

Software Theosophy

Rendering a control as an Html String in ASP.NET 2.0

It sounded simple enough. I wanted to programmatically take the contents of a form, including TextBoxes, drop down lists, checkboxes, etc and email it to my client as a sort of “snapshot” of what the user had filled out on the form.  I had done this countless times in ASP.NET 1.1, but 2.0 refused to budge.  I kept getting error after error.  Here is the basic code I was using.  Since I seem to have a mental blocks on streams, textwriters and any other part of the framework that uses the Decorator pattern I had to look it up:

 

StringWriter swriter = new StringWriter();

HtmlTextWriter twrite = new HtmlTextWriter(swriter);

this.MainPanel.RenderControl(twrite);

string text = swriter.ToString();

 

This gave me the following exception: “Control 'TextBox1' of type 'TextBox' must be placed inside a form tag with runat=server.  I remembered this from my .NET 1.1, and my solution had been to create a server side form on the fly, in the code behind it, place my controls that I wanted to render into that, then render the form.  The code would then look like this:

 

StringWriter swriter = new StringWriter();

HtmlTextWriter twrite = new HtmlTextWriter(swriter);

HtmlForm form = new HtmlForm();

form.Controls.Add(this.MainPanel);

form.RenderControl(twrite);

string text = swriter.ToString();

 

Unfortunately, this code didn’t work either.  I got another exception: “HtmlForm cannot render without a reference to the Page instance.  Make sure your form has been added to the control tree.  This left me puzzled.  I did NOT remember this from asp.net 1.1.  What does the framework care if I create an Html form without binding it to the page?  What’s changed from asp.net 1.1 to 2.0?

 

Still I tried to give it what it wanted with this line of code:

 

form.Page = this.Page;

 

Still, ASP.NET was not satisfied.  I now got another error: “RegisterForEventValidation can only be called during Render();  By now I was cursing Microsoft and spouting obscenities to myself.  Fortunately, only one other developer named Tina was around and she’s used to me by now.


I searched over and over in google for a way of successfully rendering a control as an html string which showed me a bunch of code that worked in 1.1.  Finally, after all my research, I found the answer.  In ASP.NET 2.0, you must do two things.  First override the VerifyRenderingInServerForm() method.  You don’t have to actually do anything in this method, just override it.  This ensures that you don’t have to create the HtmlForm, but you do have to override this method in your page.  Next, you have to set a page directive: EnableEventValidation="false".  This turns off event validation which basically means ASP.NET no longer checks to see if content in your controls contains malicious code.  There is a vague MSDN article here.

 

I don’t know why so much changed since ASP.NET 1.1 that the old code didn’t work.  But my real question to Microsoft is this: Why doesn’t EVERY control have a RenderAsString() method that will automatically do this for me?  Why do I have to jump through all these hoops to get a string from my controls?  This seems like very common functionality.  In any case, these two things got it to work, so you can take a control and render it as a string and email it, save it to disk or whatever.  All the research has been done for you, and here is my final example code.  This example takes the resulting string and stores it to a file on disk, but you could email it, save it to a database or whatever you wanted.

 

Default.aspx

 

<%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" EnableEventValidation="false"  %>

 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

 

<html xmlns="http://www.w3.org/1999/xhtml" >

<head runat="server">

    <title>Untitled Page</title>

</head>

<body>

    <form id="form1" runat="server">

    <div>

        <asp:Panel runat="server" ID="MainPanel">

            <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>

            <asp:Button ID="SendButton" runat="server" OnClick="SendButton_Click" Text="Send" /></asp:Panel>

    </div>

    </form>

</body>

</html>

 

 

Default.aspx.cs

 

using System;

using System.Data;

using System.Configuration;

using System.Web;

using System.Web.Security;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

using System.Web.UI.HtmlControls;

 

using System.Text;

using System.IO;

 

public partial class _Default : System.Web.UI.Page

{

    protected void Page_Load(object sender, EventArgs e)

    {

 

    }

      protected void SendButton_Click(object sender, EventArgs e)

      {

            StringWriter swriter = new StringWriter();

            HtmlTextWriter twrite = new HtmlTextWriter(swriter);

            this.MainPanel.RenderControl(twrite);

            string text = swriter.ToString();

 

            File.WriteAllText(Server.MapPath("~/output.htm"), text);

      }

 

      public override void VerifyRenderingInServerForm(Control control)

      {

           

      }

}

 

Published Saturday, September 09, 2006 10:00 PM by Fregas
Filed Under: , ,

Comments

 

janettel said:

This article is excellent.  I started down the same path with trying to create a new form..... got the same error you got - thank God for Google!!!

I am new to .NET and this information was invaluable.  Thanks again!!!  You saved me so much time!!!
October 18, 2007 2:44 PM
 

Fregas said:

You're welcome (and I'm sure google appreciates it too.)

I don't know why MS doesn't build this functionality straight into asp.net.  its so basic.
October 18, 2007 3:21 PM
 

DotNetKicks.com said:

You've been kicked (a good thing) - Trackback from DotNetKicks.com
December 16, 2007 9:49 PM
 

registerforeventvalidation can only be called said:

June 11, 2008 10:51 AM
 

Mike said:

Hi,

I have the same problem but my code is inside a user web control.  The override to VerifyRenderingInServerForm does not work there.  The EnableEve... is not a property for the <%@Control tag..
Have do you know of any work around for this situation?

This is my page setting: Master Page -> Page -> User Control.

Thanks in advance.
July 30, 2008 10:50 AM
 

Fregas said:

Mike, you can actually modify this property on the parent page, but it requires the use of reflection, because its not made public and is only settable thru the page's directives.  Send me a private message if you still need this and I can send you some code I use to encapsulate this whole process.
August 4, 2008 9:18 AM
 

K30 Girl Video, K30 Cell said:

May 20, 2010 8:25 PM
 

Chevrolet R3500 Full Tail Light, R350 Aftermarket High Samsung Freeform said:

May 21, 2010 5:13 AM
 

Amazon 600sl Wholesale, Mercedes 600sl Transmission Pan said:

May 21, 2010 4:42 PM
 

Corolla Concept, 1978 Corolla Craigslist said:

May 21, 2010 5:27 PM
 

1994 Hyundai Scoupe Parts Headlight Assembly Tail Light, Full Hyundai Scoupe Rear Bumper said:

May 21, 2010 10:38 PM
 

Miata Mx 5 Roadster Club Automatic Transmission, Ford Taurus Station Wagon All Wheel Drive said:

May 22, 2010 10:48 AM
 

Cb350 Front Wheel, Pb350 Aftermarket Brake Vacuum - 39.jeepsunlimted.com said:

May 23, 2010 6:51 AM
 

Ann Arbor Pb250 Review, Pb25 Bar - 320.defutbolazo.com said:

May 24, 2010 6:54 AM
 

Rapidshare 380sec, 380sec Heater 1983 Mercedes Benz - 199.tgrconversions.com said:

May 24, 2010 12:29 PM
 

Coupon 500sec Mercedes 300sd, 300sdl Aftermarket Brake Pads 1987 Mercedes Benz - 442.eumreborn.com said:

May 24, 2010 11:59 PM
 

Astrology Signs Body Parts, Sports Authority Astro - 37.1fh.org said:

May 25, 2010 12:20 PM
 

Download J2000 Commercial Garment Steamer, Parts J2000 Sunbird 2003 Pontiac Grand Prix Catalog - 383.myipgirl.com said:

May 25, 2010 3:16 PM
 

1995 Cadillac Seville Sts Reliability, 03 Seville Headlight Used Cadillac - 151.rkwrh.com said:

May 25, 2010 3:34 PM
 

2001 Is300 Parts Lexus Gs400, Gs400 Bulb Is300 Lexus Sc300 - 492.unlockiphone30.net said:

May 25, 2010 8:09 PM
 

Dodge W100 Pickup Bulb Body Parts, Ford Econoline 350 Sale Super Duty - 294.mfbattle.com said:

May 25, 2010 9:43 PM
 

1990 - 1986 @ Plymouth Volare Order Car Parts, Used 1980 Plymouth Volare Gran Fury Dodge Diplomat - 242.renters.ws said:

May 31, 2010 1:35 AM
Anonymous comments are disabled

About Fregas

Craig is currently the Lead Developer in Fort Worth, Texas for Enilon Group, a web development firm. He has been programming since 3rd grade (using the Commodoore PET) and professionally for the past 7 years. He has written several articles for ASPToday.com and co-authored the book "Beginning Web Programming using VB.NET and Visual Studio .NET" Currently, his favorite programming language is C#, but he has programmed in Visual Basic, T-SQL, Ruby, ColdFusion, ASP 3.0/VBScript, ASP.NET, Javascript, Java and even Pascal. Besides programming, Craig is best known for his cooking and his somewhat offbeat sense of humor.

This Blog

Post Calendar

<September 2006>
SuMoTuWeThFrSa
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

Syndication

Powered by Community Server, by Telligent Systems