2009-02-04 34 views
23

Tôi có một GridView ràng buộc với một ObjectDataSource. Tôi cũng có hỗ trợ chỉnh sửa, hoạt động tốt. Tuy nhiên, tôi muốn văn bản HtmlEncode an toàn được hiển thị khi chúng tôi cho phép các ký tự đặc biệt trong một số trường nhất định. Đây là một cinch để làm với BoundFields tiêu chuẩn, vì tôi chỉ cần thiết lập HtmlEncode thành true.Cách sử dụng HtmlEncode với TemplateFields, Data Binding và GridView

Nhưng để thiết lập kiểm soát xác thực, bạn cần sử dụng TemplateFields thay thế. Làm cách nào để dễ dàng thêm HtmlEncoding vào đầu ra theo cách này? Đây là một dự án ASP.NET 2.0, vì vậy tôi đang sử dụng các phím tắt ràng buộc dữ liệu mới hơn (ví dụ: EvalBind).

Những gì tôi muốn làm là một cái gì đó như sau:

<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> 

Tuy nhiên, khi tôi thử nó theo cách này, tôi nhận được lỗi sau:

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

Trả lời

17

Trích từ 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}").

Bạn có thể sử dụng Eval thay vì Bind trong EditItemTemplate của bạn. Bạn cũng cần phải cast đến chuỗi:

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

Để xử lý khi Mô tả là NULL trong đó quá trình truyền sẽ gây ra sự cố, hãy xem xét sử dụng phương thức ToString(): HtmlEncode (Eval ("Description"). ToString()) –

2

Bind() được sử dụng cho Two-Way Data Binding, để làm việc này bạn sẽ phải sử dụng sự kiện RowUpdating của 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()); 
    } 
} 
0

Nhưng hãy cẩn thận nếu bạn sử dụng mã sau từ Phaedrus và bạn có cột kiểm tra!

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

entry.Value.ToString() sẽ làm cho đúng từ Checkbox là True và sau đó bạn không thể lưu nó trong lĩnh vực cơ sở dữ liệu!

8

Như đã được giải thích bởi Darin Dimitrov bạn không thể sử dụng Bind làm thông số của hàm. Vì vậy, Text='<%# System.Web.HttpUtility.HtmlEncode(Bind("Description")) %>' là không thể. Ở phía bên kia nó thường không cần thiết để sử dụng HtmlEncode ở đây bởi vì bạn sẽ sử dụng Bind với một điều khiển cho phép thay đổi dữ liệu, ví dụ cùng với một TextBox (như trong ví dụ của EditItemTemplate của bạn). Nhưng một TextBox mã hóa tự động, vì vậy bạn có thể an toàn gọi Bind mà không cần HtmlEncode:

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

Nếu một TextBox sẽ không mã hóa tự động sử dụng Bind sẽ là một lỗ hổng bảo mật rất lớn (trừ khi bạn hoàn toàn chắc chắn rằng bạn dữ liệu được an toàn để được trả về HTML mà không cần mã hóa).

Nhưng mã hóa tự động KHÔNG phải là trường hợp cho nhãn chẳng hạn. Mặc dù bạn cũng có thể sử dụng Bind trong thuộc tính Văn bản của nhãn, đầu ra cho nhãn KHÔNG được mã hóa tự động - lý do tại sao sử dụng Bind với nhãn không phải là phương pháp hay vì bạn không thể mã hóa văn bản nhãn với Bind. Thay vào đó hãy sử dụng Eval và bọc nó vào HtmlEncode như bạn đã làm trong ItemTemplate của mình: Text='<%# System.Web.HttpUtility.HtmlEncode((string)Eval("Description")) %>'

1

Còn phương pháp mở rộng đơn giản thì sao?

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

Sau đó, bạn có thể chỉ cần chạy:

<asp:Label runat="server" Text=<%# ((string)Eval("MyStringField")).HtmlEncode() %> /> 
6
<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> 
28

này bây giờ có thể làm bằng cách sử dụng cú pháp databinding mã HTML mới được giới thiệu trong ASP.NET 4.

Bạn chỉ có thể sử dụng:

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

Hoặc

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

Lưu ý dấu hai chấm sau dấu thăng/băm Nó là si mple như vậy.

+1

Waww .. Một triệu đô la trả lời .. –

1

Trong trường hợp của mình, tôi đã buộc phải sử dụng phương thức "Bind" trên TextBox của mi EditItemTemplate vì cần dữ liệu có thể truy cập trong mảng NewValues ​​tại xử lý sự kiện item_Updating. Vì vậy, tôi đã tìm ra như sau:

trên EditItemTemplate tôi:

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

sau đó trong các mã sau:

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

Giải pháp này cho phép tôi để hiển thị đúng một dữ liệu html mã hóa cho tất cả các TextBox của tôi và đồng thời có thể truy cập dữ liệu này từ mảng newValues ​​khi sự kiện item_Updating kích hoạt.

Các vấn đề liên quan