How to use HtmlEncode with TemplateFields, Data Bi

2019-01-22 07:20发布

问题:

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

回答1:

This is now possible to do using the new HTML encoding databinding syntax introduced in ASP.NET 4.

You can simply use:

<%#: Eval("MyField") %>

Or

<%#: Bind("MyField") %>

Note the colon after the pound/hash sign It's as simple as that.



回答2:

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

it generates some special code for it. When you use 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:

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")) %>' />


回答3:

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")) %>'



回答4:

<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(Convert.ToString(Eval("Description"))) %>' /> 
  </ItemTemplate> 
</asp:TemplateField> 


回答5:

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());
    }
}


回答6:

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() %> />


回答7:

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.



回答8:

In my case I was forced to use the "Bind" method on mi EditItemTemplate's TextBox because needed the data to be accessible in the NewValues array at the item_Updating event handling. So i figured out as follow:

on my EditItemTemplate :

<EditItemTemplate>
     <asp:TextBox runat="server" Text='<%# Bind("field")%>' ID="TextBox112" OnPreRender="TextBox_PreRender_decode"></asp:TextBox>                                            
</EditItemTemplate> 

then in the code behind :

protected void TextBox_PreRender_decode(object sender, EventArgs e)
{
    TextBox tb = (TextBox)sender;
    tb.Text = WebUtility.HtmlDecode(tb.Text);
}

This solution allowed me to show properly an html-encoded data for all of my TextBoxes and at the same time being able to access this data from the newValues array when the item_Updating event fires.



回答9:

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!