ViewState + Ajax
От: Burd Украина http://proxysearcher.sourceforge.net
Дата: 13.08.10 13:49
Оценка:
Здраствуйте! Нашел багу в ASP.NET, она репродюсится по крайней мере для IE7 и связана с тем, что на postback приходит начальный ViewState, а не текущий.

1. Приложение
Создаю вебсайт с одной станичкой, версия .NET Framework 3.5.
В этой страниче пишу такой код на Markup'e:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebApplication1._Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
    <title>Untitled Page</title>
</head>
<body>
    <form id="form1" runat="server">
    <asp:ScriptManager ID="ScriptManager1" runat="server" />
    <asp:UpdatePanel ID="UpdatePanel1" runat="server">
        <ContentTemplate>
            <div>
                <asp:Repeater ID="Repeater1" runat="server" EnableViewState="false">
                    <HeaderTemplate>
                        <asp:TextBox ID="AddText" runat="server"></asp:TextBox>
                        <asp:Button ID="AddButton" runat="server" Text="Add"></asp:Button>
                        <br />
                    </HeaderTemplate>
                    <ItemTemplate>
                        <asp:HiddenField ID="HiddenField1" runat="server"></asp:HiddenField>
                        <asp:Label ID="Label1" runat="server"></asp:Label>
                        <asp:Button ID="DeleteButton" runat="server" Text="Delete"></asp:Button>
                    </ItemTemplate>
                </asp:Repeater>
            </div>
        </ContentTemplate>
    </asp:UpdatePanel>
    </form>
</body>
</html>


Code behind следующий:

using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Collections.Generic;

namespace WebApplication1
{
    public partial class _Default : System.Web.UI.Page
    {
        List<string> Lines
        {
            get
            {
                return (List<string>)ViewState["Lines"];
            }
            set
            {
                ViewState["Lines"] = value;
            }
        }

        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                Lines = new List<string>() { "First", "Second" };
            }

            Repeater1.ItemDataBound += Repeater1_ItemDataBound;

            BindLines();

            AddLineButton.Click += AddLineButton_Click;
        }

        private void BindLines()
        {
            Repeater1.DataSource = Lines;
            Repeater1.DataBind();
        }

        void AddLineButton_Click(object sender, EventArgs e)
        {
            Lines.Add(AddLineTextBox.Text);
            BindLines();
        }

        private Button AddLineButton
        {
            get
            {
                List<Control> res = FindControls(Repeater1.Controls, item => ((RepeaterItem)item).ItemType == ListItemType.Header);

                return (Button)res[0].FindControl("AddButton");
            }
        }

        private TextBox AddLineTextBox
        {
            get
            {
                List<Control> res = FindControls(Repeater1.Controls, item => ((RepeaterItem)item).ItemType == ListItemType.Header);

                return (TextBox)res[0].FindControl("AddText");
            }
        }

        private void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e)
        {
            if (e.Item.ItemType != ListItemType.AlternatingItem && e.Item.ItemType != ListItemType.Item)
                return;

            Label label = (Label)e.Item.FindControl("Label1");
            label.Text = (string)e.Item.DataItem;

            Button deleteButton = (Button)e.Item.FindControl("DeleteButton");
            deleteButton.Command += deleteButton_Command;
            deleteButton.CommandArgument = e.Item.ItemIndex.ToString();
        }

        private void deleteButton_Command(object sender, CommandEventArgs e)
        {
            int index = int.Parse(e.CommandArgument.ToString());
            Lines.RemoveAt(index);
            BindLines();
        }

        private List<Control> FindControls(System.Web.UI.ControlCollection controls, Predicate<Control> match)
        {
            List<Control> res = new List<Control>();

            foreach (Control control in controls)
            {
                if (match(control))
                    res.Add(control);
            }

            return res;
        }
    }
}


2. Как репродюсить: Открыть IE7, увидеть две строки которые можно удалить, удалить одну, зайти в текстовое поле, написать текст, нажать два раза Esc, текст очищается, написать текст (можно другой), нажать добавить. В результате видим три строки вместо двух.

Внимание, вопрос! Как это пофиксить?
Любая задача имеет решение, даже когда решения не существует
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.