Render User Control and Fire Control Events - c#

I'm trying to load a user control in code and store the output as a string variable. At the moment I've got the below code:
StringWriter sw = new StringWriter();
HtmlTextWriter htw = new HtmlTextWriter(sw);
WidgetControlBase widget = (WidgetControlBase)LoadControl("/controls/mycontrol.ascx");
widget.RenderControl(htw);
The problem is that the RenderControl method doesn't fire any of the control events so anything I add in the control Page_Load doesn't happen.
I've tried loading the control in a PlaceHolder and then rendering the PlaceHolder like so:
StringWriter sw = new StringWriter();
HtmlTextWriter htw = new HtmlTextWriter(sw);
WidgetControlBase widget = (WidgetControlBase)LoadControl("/controls/mycontrol.ascx");
myPlaceholder.Controls.Add(widget);
myPlaceholder.RenderControl(htw);
However this seems to do the same as just using RenderControl direct on the control, it doesn't fire any events either.
Is there a way I can get a string containing the contents of my control while still firing the control events?

I think you are trying to render the control at the wrong point in the pages life cycle. Try moving the code from Page_Load to PreInit like so:
protected override void OnPreInit(EventArgs e)
{
//custom code
base.OnPreInit(e);
}
Detailed information about the page life cycle can be found here:
http://www.codeasp.net/articles/asp.net/20/aspnet-page-lifecycle

Related

How can I force Master Render event to fire with partial rendering enabled?

I have some code in the Render event of my Master page that needs to be run on every postback, as it's used to translate some of the HTML content. However, the event does not seem to trigger on postback when I'm using an UpdatePanel and a ScriptManager with partial rendering set to true. Can I force the event to fire, or can I run my code elsewhere to produce the same result?
protected override void Render(HtmlTextWriter writer)
{
string originalContent = String.Empty;
string translatedContent = String.Empty;
using (StringWriter sw = new StringWriter())
{
using (HtmlTextWriter htw = new HtmlTextWriter(sw))
{
base.Render(htw);
htw.Close();
originalContent = sw.ToString();
}
}
// Translate content:
translatedContent = ApplyGlobalization(Page, originalContent);
// Write updated HTML:
writer.Write(translatedContent);
}
Solved the problem by creating my own UpdatePanel with Render overridden. I put the same code into that method, but had to make some changes to adjust to the translation method to accustom to the special output that the UpdatePanel creates on partial postback.

Control xxx of type 'LinkButton' must be placed inside a form tag with runat=server

I have a DataGrid that I am trying to export when an ASP.NET Button is clicked.
The exact error is:
Control 'ctl00_body_RollupDG_ctl02_btnShowGLdetail' of type 'LinkButton' must be placed inside a form tag with runat=server.
I found similar questions on here, but all seem to indicate that this comes from the ASP.NET control NOT being placed within a ContentPlaceHolder or a ContentPlaceHolder NOT being placed within a RunAt Server form.
I have both of these, so that is not the case here.
My ExportExcelFile method catches the HttpException at RenderControl() (as shown in the screenshot above). That code is as follows:
protected void ExportExcelFile(object Sender, EventArgs e) { //export to excel
var grdResults = (periodCriteria.SelectedValue == "year") ? RollupDG : QuarterDG;
var response = HttpContext.Current.Response;
response.Clear();
response.Charset = String.Empty;
response.ContentType = "application/vnd.ms-excel";
response.AddHeader("Content-Disposition", "attachment; filename=GlBudgetReport.xls");
using (var sw = new StringWriter()) {
using (var htw = new HtmlTextWriter(sw)) {
grdResults.RenderControl(htw);
response.Write(sw.ToString());
response.End();
}
}
}
As shown in my Find Results box below, there are several ASP.NET LinkButton controls, but each of them does contain the runat="server" clause.
It appears the LinkButton data in the DataGrid has difficulty rendering as Plain Text.
If not, is there something in my export method that can be configured so that the DataGrid data is all interpreted as text?
I could create a blank DataGrid, then walk through the filled DataGrid, writing in only the text of each field - but I only want to do this if it is absolutely necessary.
I believe you just need to override the method that checks for a form. You don't need to add any logic to the method. Just add the following to your code behind:
public override void VerifyRenderingInServerForm(Control control) { }
ETA: You may also need to set EnableEventValidation="false" in the <%#Page /> element.

Artificially firing Page Events in ASP.NET?

I'm working with a static class in C#, and am trying to use Control.RenderControl() to get a string / mark-up representation of a Control.
Unfortunately the control (and all child controls) use event bubbling to populate certain values, for example, when instantiating, then calling RenderControl() on the following:
public class MyTest : Control
{
protected override void OnLoad(EventArgs e)
{
this.Controls.Add(new LiteralControl("TEST"));
base.OnLoad(e);
}
}
I am returned an empty string, because OnLoad() is never fired.
Is there a way I can invoke a 'fake' page lifecycle? Perhaps use some dummy Page control?
I was able to accomplish this by using a local instance of Page and HttpServerUtility.Execute:
// Declare a local instance of a Page and add your control to it
var page = new Page();
var control = new MyTest();
page.Controls.Add(control);
var sw = new StringWriter();
// Execute the page, which will run the lifecycle
HttpContext.Current.Server.Execute(page, sw, false);
// Get the output of your control
var output = sw.ToString();
EDIT
If you need the control to exist inside a <form /> tag, then simply add an HtmlForm to the page, and add your control to that form like so:
// Declare a local instance of a Page and add your control to it
var page = new Page();
var control = new MyTest();
// Add your control to an HTML form
var form = new HtmlForm();
form.Controls.Add(control);
// Add the form to the page
page.Controls.Add(form);
var sw = new StringWriter();
// Execute the page, which will in turn run the lifecycle
HttpContext.Current.Server.Execute(page, sw, false);
// Get the output of the control and the form that wraps it
var output = sw.ToString();

Loading a user control dynamically

I'm trying to load a user control in a web service, but it doesn't execute the Load_Page().
I tried to use:
HttpContext.Current.Server.Execute(page, text, false);
But it returns a NullException. It is my code:
public string Controle(string url)
{
Page page = new Page();
UserControl userControl = (UserControl)page.LoadControl(url);
//userControl.EnableViewState = false;
HtmlForm form = new HtmlForm();
form.Controls.Add(userControl);
page.Controls.Add(form);
StringWriter text = new StringWriter();
HtmlTextWriter htmltext = new HtmlTextWriter(text);
userControl.RenderControl(htmltext);
return text.ToString();
}
Hope it is clear.
You need to initialize the control using a method that does something like
this.Load += Page_Load;
Please refer to this post which explains exactly what needs to be done to achieve this. Be sure to read the section stating; "One word of caution:"
http://weblogs.asp.net/srkirkland/archive/2007/11/05/dynamically-render-a-web-user-control.aspx
This related post will also be able to assist:
Page_Load not firing in UserControl

Render HtmlGenericControl from a HttpHandler

I have a set of code (noted below) in ProcessRequest(HttpContext context) in a generic handler .ashx file.
HtmlGenericControl holder = new HtmlGenericControl("div");
//Set holder's properties and customization
HtmlGenericControl button1 = new HtmlGenericControl("input");
//Set button1's properties and customization
holder.Controls.Add(button1);
HtmlGenericControl button2 = new HtmlGenericControl("input");
//Set button2's properties and customization
holder.Controls.Add(button2);
HtmlGenericControl button2 = new HtmlGenericControl("input");
//Set button2's properties and customization
holder.Controls.Add(button2);
Now as I am in a HttpHander, I want to get the HTML of holder control and write it through context.Respose.Write().
Please help me through this.
Thanks in advance
Munim
I have figured out the way by myself.
using (StringWriter stringWriter = new StringWriter())
{
HtmlTextWriter htmlTextWriter = new HtmlTextWriter(stringWriter);
holder.RenderControl(htmlTextWriter);
HttpContext.Response.Write(stringWriter.ToString());
htmlTextWriter.Close();
stringWriter.Close();
}

Categories

Resources