I think you are attacking it from the wrong angle by trying to encode all posted data.
Note that a "<
" could also come from other outside sources, like a database field, a configuration, a file, a feed and so on.
Furthermore, "<
" is not inherently dangerous. It's only dangerous in a specific context: when writing strings that haven't been encoded to HTML output (because of XSS).
In other contexts different sub-strings are dangerous, for example, if you write an user-provided URL into a link, the sub-string "javascript:
" may be dangerous. The single quote character on the other hand is dangerous when interpolating strings in SQL queries, but perfectly safe if it is a part of a name submitted from a form or read from a database field.
The bottom line is: you can't filter random input for dangerous characters, because any character may be dangerous under the right circumstances. You should encode at the point where some specific characters may become dangerous because they cross into a different sub-language where they have special meaning. When you write a string to HTML, you should encode characters that have special meaning in HTML, using Server.HtmlEncode. If you pass a string to a dynamic SQL statement, you should encode different characters (or better, let the framework do it for you by using prepared statements or the like)..
When you are sure you HTML-encode everywhere you pass strings to HTML, then set ValidateRequest="false"
in the <%@ Page ... %>
directive in your .aspx
file(s).
In .NET 4 you may need to do a little more. Sometimes it's necessary to also add <httpRuntime requestValidationMode="2.0" />
to web.config (reference).
To register a control as a trigger for a postback, use ScriptManager's RegisterPostBackControl Method.
If editLink IsNot Nothing Then
ScriptManager.GetCurrent(this.Page).RegisterPostBackControl(editLink )
End If
This methods works too for controls dynamically added within other controls.
I had the same problem with my GridView. I've registered linkButton and imageButton of a TemplatedField row.
I use RowCreated Gridview's handler instead of RowDataBound handler :
RowCreated is focused on parsing Gridview row's definition and creating the Gridview row's control structure,
RowDataBound is focused on bind data to the row's controls created in the RowCreated.
Also RowCreated is invoked automatically in both init and postback case, but RowDataBound is only invoke when the DataBind is called.
Code
<asp:GridView ID="ContactsGridView" runat="server" AutoGenerateColumns="False"
DataSourceID="ContactsContainerDataSource" EnableViewState="false"
DataKeyNames="CompanyID,ContactId" AllowSorting="True" AllowPaging="true"
OnRowCreated="ContactsGridView_RowCreated" PageSize="10" CssClass="GridSimple"
OnRowCommand="ContactsGridView_RowCommand">
<Columns>
<asp:TemplateField HeaderStyle-CssClass="large" HeaderText="Contact" SortExpression="ContactNom">
<ItemTemplate>
<asp:ImageButton ID="PreviewImageButton" runat="server" ImageUrl="../images/picto_pdf.gif"
CommandName="PreviewContact" CommandArgument=<%#Eval("ContactCode") %> BorderWidth="0"
ToolTip="View Pdf Document" />
<asp:LinkButton ID="ContactNamePreviewLinkButton" runat="server" CommandName="Select"
CommandArgument='<%#Eval("ContactCode") %>'><%#Eval("ContactName")%></asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
protected void ContactsGridView_RowCreated(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
//Register download buttons as PostBack controls (instead of AsyncPostback because of their updatepanel container))
ImageButton ib = (ImageButton)e.Row.FindControl("PreviewImageButton");
if (ib != null) ScriptManager.GetCurrent(this.Page).RegisterPostBackControl(ib);
LinkButton lb = (LinkButton)e.Row.FindControl("ContactNamePreviewLinkButton");
if (lb != null) ScriptManager.GetCurrent(this.Page).RegisterPostBackControl(lb);
}
}
protected void ContactsGridView_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "PreviewContact")
{
_presenter.OnPreviewContactClicked((string)e.CommandArgument);
}
}
Best Answer
I've solved this by accessing the ScriptManager on the page instead of the UpdatePanel itself. I did this inside the Page_Load method. My code is as follows: