Google+ Peter Bromberg's .NET Blog | All posts by admin

Peter Bromberg's .NET Blog All Things Programming

An Easy Way to Render HTML From an ASP.NET UserControl

20. March 2013 09:59 by admin in

Often we need to call RenderControl on a UserControl to get the rendered HTML and be able to pass it to a PDF or Report generator. This can be problematic because you will get exceptions saying that the control must be within a FORM tag with runat=server. Also, If there are any AJAX script - related controls such as TextBoxExtenders, you will be warned that a ScriptManager is required. Here is an easy way to avoid these issues and get back "clean" HTML:

public static string RenderUserControl(Control ctrl)

{

Control control = null;

const string STR_BeginRenderControlBlock = "";

const string STR_EndRenderControlBlock = "";

StringWriter tw = new StringWriter();

Page page = new Page();

page.EnableViewState = false;

HtmlForm form = new HtmlForm();

form.ID = "__temporanyForm";

page.Controls.Add(form);

form.Controls.Add(new LiteralControl(STR_BeginRenderControlBlock));

// add a ScriptManager to prevent Ajax Extender control exceptions

ScriptManager m = new ScriptManager();

form.Controls.Add(m);

form.Controls.Add(ctrl);

form.Controls.Add(new LiteralControl(STR_EndRenderControlBlock));

HttpContext.Current.Server.Execute(page, tw, true);

string Html = tw.ToString();

int start = Html.IndexOf("");

int end = Html.Length - start;

Html = Html.Substring(start, end);

// return the rendered HTTML and send it into the PDF generator

return Html;

}

ASP.NET Strongly Typed Data Controls

10. March 2013 11:49 by admin in

ASP.NET Web Forms introduced the concept of "templates",  which allow you to customize the markup emitted from server controls, and are typically used with data-binding expressions.

When using data-binding within a template today, you use late-bound expressions to bind to the data.  Below we are using the Eval() helper method to data-bind the "FirstName" and "LastName" properties from a list of objects data-bound to a repeater control:

<ul>

    <asp:Repeater runat="server" ID="customers">

        <ItemTemplate>

            <li>

                First Name: <%# Eval("FirstName") %><br />

                Last Name: <%# Eval("LastName") %><br />

            </li>

        </ItemTemplate>

    </asp:Repeater>

</ul>

When performing 2-way data-binding today, you use the Bind() helper method like so:

<asp:FormView ID="editCustomer" runat="server" >

    <EditItemTemplate>

        <div>

            First Name:

            <asp:TextBox ID="firstName" runat="server" Text='<%# Bind("FirstName") %>' />

        </div>

        <div>

            Last Name:

            <asp:TextBox ID="lastName" runat="server" Text='<%# Bind("LastName") %>' />

        </div>

        <asp:Button runat="server" CommandName="Update" />

    </EditItemTemplate>

</asp:FormView>

One downside with the above approaches is that the calls to Eval() and Bind() are late-bound - meaning you pass strings to represent the property names.  This means you don't get Intellisense for the member names, support for code navigation (like Go To Definition), nor compile-time checking support.

Strongly Typed Data Controls

The next release of ASP.NET provides the ability to enable strongly-typed data templates.  Specifically, we've added the ability to declare what type of data a control is going to be bound to, by way of a new "ModelType" property on data controls.  Setting this property will cause two new typed variables to be generated in the scope of the data-bound template expressions: Item and BindItem.

Developers can use these variables in data-binding expressions and get full Intellisense and compile-time checking support.  For example, below we've set the ModelType on an <asp:repeater> control to be a "Customer" object.  Once we do this we can switch from using Eval("FirstName") to instead use Item.FirstName to reference the property.

We get full Visual Studio code intellisense when we do so:

image

For 2-way data-binding expressions, we can also now use the BindItem variable and get the same strongly-typed benefits:

<asp:FormView ID="editCustomer" runat="server">

    <EditItemTemplate>

        <div>

            First Name:

            <asp:TextBox ID="firstName" Text='<%# BindItem.FirstName %>' runat="server" />

        </div>

        <div>

            Last Name:

            <asp:TextBox ID="lastName" Text='<%# BindItem.LastName %>' runat="server" />

        </div>

        <asp:Button runat="server" CommandName="Update" />

    </EditItemTemplate>

</asp:FormView>

If we make a mistake while typing, we'll get instant feedback from the IntelliSense engine that something is wrong:

image