I am trying to get the rendered HTML of Ajaxtoolkit:Editor control. I am getting an error while rendering here is my code:
[WebMethod]
public static string GetHtmlEditor()
{
CustomHTMLEditor objCustom = new CustomHTMLEditor();
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
HtmlTextWriter textWriter = new HtmlTextWriter(sw);
UpdatePanel up = new UpdatePanel();
up.ID = "upId";
up.ContentTemplateContainer.Controls.Add(objCustom);
up.RenderControl(textWriter);
return textWriter.ToString();
}
Error: Page cannot be null. Please ensure that this operation is being performed in the context of an ASP.NET request.
I tried executing directly i.e without using UpdatePanel. Still it throws the same error.
Can i render Ajaxtoolkit controls?
Related
I am creating custom HtmlHelper in ASP.NET MVC 4 that needs to render ASP.NET standard web controls like <asp:Panel> or <asp:Button>. What I mean by this is: from my HtmlHelper, I want my browser to render them same as it is a ASP.NET web form application.
I was searching on the net about this topic, but didn't find anything specific that might help me how to realize this.
If anyone has any idea how this can be realized or has any experience with this, please share it :)
If anyone has similar problem or wants to know how it can be done, here is my code.
public static MvcHtmlString Panel(this HtmlHelper html)
{
Panel pnl = new Panel();
pnl.ID = "mainPanel";
pnl.BorderStyle = BorderStyle.Solid;
pnl.BorderWidth = Unit.Pixel(1);
pnl.BorderColor = System.Drawing.Color.Black;
Label lblTitle = new Label();
lblTitle.Text = "Title";
TextBox txtTitle = new TextBox();
txtTitle.ID = "txtTitle";
lblTitle.Attributes.Add("for", "txtTitle");
Label lblMessage = new Label();
lblMessage.Text = "Message";
TextBox txtMessage = new TextBox();
txtMessage.TextMode = TextBoxMode.MultiLine;
txtMessage.ID = "txtMessage";
Label lblDepartment = new Label();
lblDepartment.Text = "Department";
DropDownList lstDepartment = new DropDownList();
lstDepartment.ID = "lstDepartment";
ListItemCollection collection = new ListItemCollection();
collection.Add(new ListItem("Department1"));
collection.Add(new ListItem("Department3"));
collection.Add(new ListItem("NoDepartment"));
lstDepartment.DataSource = collection;
lstDepartment.DataBind();
pnl.Controls.Add(lblTitle);
pnl.Controls.Add(txtTitle);
pnl.Controls.Add(lblMessage);
pnl.Controls.Add(txtMessage);
pnl.Controls.Add(lblDepartment);
pnl.Controls.Add(lstDepartment);
HtmlTextWriter writer = new HtmlTextWriter(new StringWriter());
pnl.RenderControl(writer);
return MvcHtmlString.Create(writer.InnerWriter.ToString());
}
Basically, you use the classes of the web controls you need and you create the HTML. HtmlTextWriter is used to render the things you coded for that purpose.
I have this code:
public static string RenderView(string path)
{
Page pageHolder = new Page();
UserControl viewControl = (UserControl)pageHolder.LoadControl(path);
pageHolder.Controls.Add(viewControl);
StringWriter output = new StringWriter();
HttpContext.Current.Server.Execute(pageHolder, output, false);
return output.ToString();
}
Which is run from:
[WebMethod]
public string GetReportsHTML()
{
string output = "";
output = ViewManager.RenderView("ReportsControl.ascx");
return output;
}
This is to test rendering ASCX files and spitting them out of a SOAP/REST service.
Problem is, some controls (runat=server ones) fail if they are not encapsulated in a tag with runat=server.
The solution to that is here, but the solution assumes being inside an ASPX file where I can just edit the markup.
How would I programmatically build a Page, add a Form, set runat=server so that I can follow that solution and add my control to the Form Control?
Have you tried something like this ?
public static string RenderView(string path)
{
Page pageHolder = new Page();
System.Web.UI.HtmlControls.HtmlForm formHolder = new System.Web.UI.HtmlControls.HtmlForm();
pageHolder.Controls.Add(formHolder );
UserControl viewControl = (UserControl)pageHolder.LoadControl(path);
formHolder.Controls.Add(viewControl);
StringWriter output = new StringWriter();
HttpContext.Current.Server.Execute(pageHolder, output, false);
return output.ToString();
}
Hope this will help
I develop a custom usercontrol. For a specific need, I have to get the html generate from usercontrol inside it and display only it in the page's body.
I think it's possible overloading RenderControl(HtmlTextWriter writer) but I don't know how.
Thanks
You can render the control in memory, have it on a string, and then print this string somewhere on your page as you say. Here is the code that loads the control and renders it on memory, then have the results on a string.
// load the control
var oTesto = Page.LoadControl("Testo.ascx");
// here you need to run some initialization of your control
// because the page_load is not loading now.
// a string writer to write on it
using(TextWriter stringWriter = new StringWriter())
{
// a html writer
using(HtmlTextWriter GrapseMesaMou = new HtmlTextWriter(stringWriter))
{
// now render the control inside the htm writer
oTesto.RenderControl(GrapseMesaMou);
// here is your control rendered output.
strBuild = stringWriter.ToString();
}
}
To capture the rendering of your control you can use the Render as:
protected override void Render(HtmlTextWriter writer)
{
System.IO.StringWriter stringWriter = new System.IO.StringWriter();
HtmlTextWriter htmlWriter = new HtmlTextWriter(stringWriter);
// now the control is inside the htmlWriter as final rendered text
base.Render(htmlWriter);
// here is how to make the control render itself
// base.Render(writer);
}
You place the render inside your control class.
i want to load a user control using jquery ajax. One possible i found is to load usercontrol through generic handler. Anyone help me plsss. here the ajax code i am using to call the control.
<script type="text/javascript">
function fillSigns() {
$.ajax({
url: "usercontrolhandler.ashx?control=signs.ascx",
context: document.body,
success: function (data) {
$('#signdiv').html(data);
}
});
}
</script>
and here is the code in handler file
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
Page page = new Page();
UserControl ctrl = (UserControl)page.LoadControl("~/" + context.Request["control"] + ".ascx");
page.Form.Controls.Add(ctrl);
StringWriter stringWriter = new StringWriter();
HtmlTextWriter tw = new HtmlTextWriter(stringWriter);
ctrl.RenderControl(tw);
context.Response.Write(stringWriter.ToString());
}
This code raises object reference not found error at below shown line.
page.Form.Controls.Add(ctrl);
It seems page.Form is null here, that's why you've got a null reference exception. You could add your user control to the page's control collection instead:
page.Controls.Add(ctrl);
You could also use HttpServerUtility.Execute method for page rendering:
StringWriter output = new StringWriter();
HttpContext.Current.Server.Execute(page, output, false);
And finally take a look onto Tip/Trick: Cool UI Templating Technique to use with ASP.NET AJAX for non-UpdatePanel scenarios article by Scott Guthrie which covers your problem.
Try this:
Page page = new Page {ViewStateMode = ViewStateMode.Disabled};
HtmlForm form = new HtmlForm { ViewStateMode = ViewStateMode.Disabled };
form.Controls.Add(ctrl);
page.Controls.Add(form);
then:
StringWriter stringWriter = new StringWriter();
HtmlTextWriter tw = new HtmlTextWriter(stringWriter);
page.RenderControl(tw);
context.Response.Write(stringWriter.ToString());
I want to use an ascx as a template, and render it programatically, using the resulting html as the return value of an ajax method.
Page pageHolder = new Page();
MyUserControl ctlRender = (MyUserControl)pageHolder.LoadControl(typeof(MyUserControl),null);
pageHolder.Controls.Add(ctlRender);
System.IO.StringWriter swOutput = new System.IO.StringWriter();
HttpContext.Current.Server.Execute(pageHolder, swOutput, false);
return swOutput.ToString();
This all executes, and the Page Load event of the user control fires, but the StringWriter is always empty. I've seen similar code to this in other examples, what am I missing?
Have you tried this:
public string RenderControl(Control ctrl)
{
StringBuilder sb = new StringBuilder();
StringWriter tw = new StringWriter(sb);
HtmlTextWriter hw = new HtmlTextWriter(tw);
ctrl.RenderControl(hw);
return sb.ToString();
}
Taken directly from the article here:
ASP.NET Tip: Render Control into HTML String
You always have to use something like this.Controls.Add(TemplateControl.LoadControl("~/PathTo/YourControl.ascx")
The reason is, that there is no internal mapping of Types to there ascx-file (only the other way arround). So this means if you initialize new YourControl(), it will not do anything you defined in the ascx part. If you would have
protected override void protected override void Render(HtmlTextWriter output) {
output.WriteLine("Test");
}
this would give you "Test" in the place you rendered your control to.