views:

5680

answers:

7

I have a GridView bound to an ObjectDataSource. I've got it supporting editing as well, which works just fine. However, I'd like to safely HtmlEncode text that is displayed as we do allow special characters in certain fields. This is a cinch to do with standard BoundFields, as I just set HtmlEncode to true.

But in order to setup validation controls, one needs to use TemplateFields instead. How do I easily add HtmlEncoding to output this way? This is an ASP.NET 2.0 project, so I'm using the newer data binding shortcuts (e.g. Eval and Bind).

What I'd like to do is something like the following:

<asp:TemplateField HeaderText="Description">
    <EditItemTemplate>
        <asp:TextBox ID="TextBoxDescription" runat="server"
                     Text='<%# System.Web.HttpUtility.HtmlEncode(Bind("Description")) %>'
                     ValidationGroup="EditItemGrid"
                     MaxLength="30" />
        <asp:Validator ... />
    </EditItemTemplate>
    <ItemTemplate>
        <asp:Label ID="LabelDescription" runat="server"
                   Text='<%# System.Web.HttpUtility.HtmlEncode(Eval("Description")) %>' />
    </ItemTemplate>
</asp:TemplateField>

However, when I try it this way, I get the following error:

CS0103: The name 'Bind' does not exist in the current context

+2  A: 

Quote from http://weblogs.asp.net/leftslipper/archive/2007/06/29/how-asp-net-databinding-deals-with-eval-and-bind-statements.aspx

There isn’t a Bind method in ASP.NET. When ASP.NET parses your file and sees you're using <%# Bind() %> it generates some special code for it.

When you use <%# Bind("Name") %> it's not a real function call. If ASP.NET parses the code and detects a Bind() statement, it splits the statement into two parts. The first part is the one-way databinding portion, which ends up being just a regular Eval() call. The second part is the reverse portion, which is typically some code along the lines of "string name = TextBox1.Text" that grabs the value back out from where it was bound. However, because ASP.NET has to parse Bind() statements, two-way databinding doesn’t support anything other than Bind(). For example, the following syntax is invalid because it tries to invoke arbitrary code and use Bind() at the same time:

<%# FormatNameHelper(Bind("Name")) %>

The only formats supported in two-way databinding are Bind("field") and Bind("field", "format string {0}").

You could use Eval instead of Bind in your EditItemTemplate. You also need to cast to string:

<asp:Label ID="LabelDescription" 
           runat="server" 
           Text='<%# System.Web.HttpUtility.HtmlEncode((string)Eval("Description")) %>' />
Darin Dimitrov
+1  A: 

Bind() is used for Two-Way Data Binding, for this to work you will have to use the RowUpdating event of the gridview.

void GridView_RowUpdating(Object sender, GridViewUpdateEventArgs e)
{
    foreach (DictionaryEntry entry in e.NewValues)
    {
        e.NewValues[entry.Key] = System.Web.HttpUtility.HtmlEncode(entry.Value.ToString());
    }
}
Phaedrus
A: 

The fields in the gridview are already htmlencoded. The templatefields will do this automatically.

Ben
sorry, it is not automatically encoded. i tested it.
Shankar
The answer is not that bad. Some Controls (like TextBoxes) ARE automatically encoded, others (like Labels) not. In the context of this question it is only important that TextBoxes are automatically encoded since you cannot wrap `Bind` into HtmlEncode. For labels you can use `Eval` together with HtmlEncode. In the end this solves the problem described in the question.
Slauma
Thanks Slauma. Technically I was wrong. I had vaguely remembered having to disable html encoding when working with a gridview a long time ago and must have assumed it was gridview behavior and not that of child controls. Your suggestion to use Eval is a good one.
Ben
A: 

But take care if you use following code from Phaedrus and you have a checkbox column!

void GridView_RowUpdating(Object sender, GridViewUpdateEventArgs e) { foreach (DictionaryEntry entry in e.NewValues) { e.NewValues[entry.Key] = System.Web.HttpUtility.HtmlEncode(entry.Value.ToString()); } }

Because the entry.Value.ToString() will make the true from the Checkbox to True and then you can not save it in the database field!

A: 

As already explained by Darin Dimitrov you cannot use Bind as a parameter of a function. So Text='<%# System.Web.HttpUtility.HtmlEncode(Bind("Description")) %>' is not possible. On the other side it's usually not necessary to use HtmlEncode here because you will use Bind with a control which allows to change data, for instance along with a TextBox (as in the example of your EditItemTemplate). But a TextBox encodes automatically, so you can safely call Bind without the need of HtmlEncode:

<EditItemTemplate>
    <asp:TextBox ID="TextBoxDescription" runat="server"
                 Text='<%# Bind("Description") %>'
                 ValidationGroup="EditItemGrid"
                 MaxLength="30" />
    <asp:Validator ... />
</EditItemTemplate>

If a TextBox would not encode automatically using Bind would be a huge security hole (unless you are absolutely sure that your data are safe to be rendered to HTML without encoding).

But automatic encoding is NOT the case for a label for instance. Although you can also use Bind in the Text property of a label, the output to the label is NOT encoded automatically - a reason why using Bind with a label isn't a good practice, since you cannot encode the label text with Bind. Instead use Eval and wrap it into HtmlEncode as you have done it in your ItemTemplate: Text='<%# System.Web.HttpUtility.HtmlEncode((string)Eval("Description")) %>'

Slauma
A: 

What about a simple extension method?

public static string HtmlEncode(this string s)
    {            
        s = HttpUtility.HtmlEncode(s);
        return s;
    }

You could then simply run:

<asp:Label runat="server" Text=<%# ((string)Eval("MyStringField")).HtmlEncode() %> />
BlackjacketMack
A: 

Kindly Refer to

http://forums.asp.net/p/1056231/1504717.aspx

I got the working solution from here . Its working like a charm for me ...

Regards,
Rajan Arora
www.simplyrajan.co.nr

Rajan Arora