ASP.NET AJAX UpdatePanel & Dynamic HTML Insert Issue (Telerik)



我有一个问题。我目前正在做一个使用ASP的Telerik框架的项目。. NET AJAX,尽管这应该无关紧要,因为我在这部分工作中完全(几乎)绕过了Telerik。

我正在把一个类似facebook的聊天程序整合到我们公司的CRM系统中,虽然到目前为止一切都很顺利,但我遇到了一个障碍。问题是当我尝试"创建一个新的聊天框"。我使用asp控件UpdatePanel与jQuery $结合。ajax调用将JSON方法名称传递到我的代码后文件。以下是JSON逻辑:

双击用户在userlist:

$telerik.$(".UserListEntry").dblclick(function () {
                var ToName = $telerik.$(this).children(".UserListEntryName").text();
                var FromName = $telerik.$("#lkUserGeneralSettings").text();
                $telerik.$.ajax({
                    type: 'POST',
                    url: 'DefaultHandler.ashx',
                    data: { "ToName": ToName, "FromName": FromName },
                    success: CreateChatBox(),
                    error: function (response) { alert("error: 001"); }
                });
            });

CreateChatBox回调:

function CreateChatBox() {
            $telerik.$.ajax({
                type: 'POST',
                url: 'Default.aspx',
                data: { MethodName: "CreateChatBox" },
                success: ForceAsyncPostback,
                error: function (response) { alert("error: 002"); }
            });
        }

强制asyncpostback(不应该是必需的,但这也不工作!):

function ForceAsyncPostback() {
            var UpdatePanel1 = '<%=Panel3.ClientID%>';
            if (UpdatePanel1 != null) {
                __doPostBack(UpdatePanel1, '');
            }
            alert("Success");
        }

UpdatePanel是通过各种文字和一些硬编码的htmldiv创建的。问题是不是动态创建上述元素,这工作得很好。事实上,我的代码(我将在下面发布)创建和显示一切都很好,如果我把它放在我的PageLoad事件。

, . aspx:

<asp:UpdatePanel ID="Panel3" runat="server" OnLoad="Panel3_Load" UpdateMode="Conditional">
                <ContentTemplate>
                    <asp:Literal ID="ChatBoxesLiteralTop" runat="server" />
                    <asp:Literal ID="ChatBoxesLiteralMid" runat="server" />
                    <asp:PlaceHolder ID="ChatBoxesPlaceHolder" runat="server" />
                    <asp:Literal ID="ChatBoxesLiteralBot" runat="server" />
                    <div id="UserListCorner">
                        <img id="UserListBtn" src="images/list.png" />
                    </div>
                    <div id="UserList" class="UserListHidden">
                        <div id="UserListView">
                            <asp:Literal ID="UserListViewLiteral" runat="server" />
                        </div>
                    </div>
                </ContentTemplate>
            </asp:UpdatePanel>

代码:

protected void Panel3_Load(object sender, EventArgs e)
    {
        #region Ajax methods
        if (Request.Form["MethodName"] == "CreateChatBox")
        {
            CreateChatBox();
        }
        #endregion
        Engine m_engine = new Engine();
        string m_sql = @"SELECT FullName FROM Users WHERE RecordDeleted <> 1";
        DataTable dt = m_engine.GetObjectsAsDataTable(m_sql);
        for (int i = 0; i < dt.Rows.Count; i++)
        {
            UserListViewLiteral.Text += "<div class='UserListEntry'><span class='UserListEntryStatus'><img src='images/status-online.png' width='10' /></span>&nbsp;<span class='UserListEntryName'>" + dt.Rows[i]["FullName"].ToString() + "</span></div>";
        }
        RadAjaxManager.GetCurrent(Page).ResponseScripts.Add("ChatAjax()");   
    }
    private void CreateChatBox()
    {
        ChatBoxesLiteralTop.Text = @"<div id='ChatBox' class='ChatBoxHidden'>
                                        <div class='ChatBoxHeader'>
                                            <img id='ChatBoxStatusBtn' src='Images/status-online.png' />
                                            <span id='ChatBoxUserLabel'>John Doe</span>
                                            <img id='closeBtn' src='Images/close.png' />
                                            <img id='toggleTab' src='Images/up-arrow.png' />
                                        </div>
                                        <div id='ChatBoxMessageOutput'></div><div class='ChatBoxFooter'>";
        TextBox txt = new TextBox();
        txt.ID = "ChatBoxMessageInput";
        txt.Height = 16;
        txt.MaxLength = 270;
        txt.Width = 250;
        txt.AutoPostBack = false;
        ChatBoxesPlaceHolder.Controls.Add(txt);
        RadButton btn = new RadButton();
        btn.ID = "ChatBoxSendButton";
        btn.Text = "Send";
        btn.AutoPostBack = true;
        btn.Height = 22;
        btn.Click += ChatBoxSendButton_Click;
        ChatBoxesPlaceHolder.Controls.Add(btn);
        ChatBoxesLiteralBot.Text = "</div></div>";
        Panel3.Update();
        RadAjaxManager.GetCurrent(Page).ResponseScripts.Add("ChatAjax()");
    }

我当然忽略了一些非常愚蠢的事情,但是一个经验丰富的ASP的新鲜视角。Net Ajaxer会非常感激!提前谢谢。

问题澄清

怎么做:

  • 代码运行正常。
  • JSON方法被传递给后面的代码并被读取。
  • CreateChatBox()方法贯穿并据称填充文字和控件。
  • JSON链中的所有回调都成功执行。

不工作的地方:

  • UpdatePanel,即使在冗余回发之后,也没有代码成功执行后的新HTML。

致相关人员


好吧,我碰巧在发布后的第二天解决了这个问题。当然,现在有新的障碍需要解决,但我很高兴地说,我的异步聊天模块几乎完成了。由于没有人决定承担这个问题,我将发布我在ASP中基于硬编码的HTML正确生成动态异步对象的方法。当我在谷歌上搜索这件事时,这篇文章是唯一弹出的相关结果。

我首先要说的是,我很清楚这是一种非常非常规的方法。话虽如此,项目的需求证明了方法的合理性。虽然可能有很多其他的方法来实现你的目标,但这个方法确实有效。关于我的特殊项目,我不打算进入无关的细节,但希望这将在未来帮助别人。

错误

我最初的问题的主要问题是我攻击渲染序列的方式。我的逻辑中的一个主要缺陷是试图将ASP控件(文字、占位符、按钮等)从HTML中分离太多。我最初的方法(从上面)是这样的:

<asp:UpdatePanel ID="Panel3" runat="server" OnLoad="Panel3_Load" UpdateMode="Conditional">
            <ContentTemplate>
                <asp:Literal ID="ChatBoxesLiteralTop" runat="server" />
                <asp:Literal ID="ChatBoxesLiteralMid" runat="server" />
                <asp:PlaceHolder ID="ChatBoxesPlaceHolder" runat="server" />
                <asp:Literal ID="ChatBoxesLiteralBot" runat="server" />
                <div id="UserListCorner">
                    <img id="UserListBtn" src="images/list.png" />
                </div>
                <div id="UserList" class="UserListHidden">
                    <div id="UserListView">
                        <asp:Literal ID="UserListViewLiteral" runat="server" />
                    </div>
                </div>
            </ContentTemplate>
</asp:UpdatePanel>

最终的结果看起来更像这样:

<asp:UpdatePanel ID="Panel3" runat="server" OnLoad="Panel3_Load" UpdateMode="Conditional">
                <ContentTemplate>
                    <asp:PlaceHolder ID="ChatBoxesPlaceHolder" runat="server" />
                    <div id="UserListCorner">
                        <img id="UserListBtn" src="images/list.png" />
                    </div>
                    <div id="UserList" class="UserListHidden">
                        <div id="UserListView">
                            <asp:Literal ID="UserListViewLiteral" runat="server" />
                        </div>
                    </div>
                    <asp:Label ID="Label42" Font-Bold="true" runat="server" />
                    <asp:HiddenField runat="server" ID="LatestDisplayTick" />
                </ContentTemplate>
</asp:UpdatePanel>

后面的代码(删节)类似如下:

Literal top = new Literal();
// ...
UpdatePanel UpdatePanel2 = new UpdatePanel();
// ...
top.Text = @"<div id='ChatBox' class='ChatBoxShown'>
                                             <div class='ChatBoxHeader'>
                                                 <img id='ChatBoxStatusBtn' src='Images/status-online.png' />
                                                 <span id='ChatBoxUserLabel'>" + UserNames[0] + @"</span>
                                                 <img id='closeBtn' src='Images/close.png' />
                                                 <img id='toggleTab' src='Images/up-arrow.png' />
                                             </div>";
top.ID = "ChatBoxesLiteralTop";
top.Mode = LiteralMode.PassThrough;
// ...
UpdatePanel2.ID = "UpdatePanel2";
UpdatePanel2.UpdateMode = UpdatePanelUpdateMode.Conditional;
UpdatePanel2.ChildrenAsTriggers = false;
UpdatePanel2.ContentTemplateContainer.Controls.Add(top2);
// ...
Panel3.ContentTemplateContainer.Controls.Add(top);
Panel3.ContentTemplateContainer.Controls.Add(UpdatePanel2);               
Panel3.ContentTemplateContainer.Controls.Add(mid);

含义


我所做的就是将我的chatbox元素全部包装在一个占位符中,动态地创建HTML元素来包装来自服务器的ASP控件,并将其作为动态数据的"块"发布。这避免了ASP控件放置的一些奇怪行为,并允许对我的项目的客户端功能采用准oo方法。创建之后,我现在可以使用一些JSON和AJAX调用来将数据动态地输入到所述动态创建的控件中。

一个例子将张贴从数据库通知收到的消息到我的聊天窗口(ChatBoxesLiteralMid控件),当它收到。

After Page/Control Load

if(ChatBoxesLiteralMid != null)
            ChatBoxesLiteralMid.Text += @"<div class='ChatBoxEntry'><span class='ChatBoxEntryName ChatBoxSelf'>" + AppParameters.Current.AppUser.FirstName + "</span>:&nbsp;<span class='ChatBoxEntryMessage'>" + dy.Rows[dy.Rows.Count - 1]["Message"].ToString() + "</span></div>";

为什么要这么麻烦?


我所完成的是一个特定的项目,需要远远超出原来的范围,由另一个开发人员几年前开始。这是教老狗一些新把戏的一种非传统的方法。我现在几乎完全控制了客户端任意数量的实时聊天框/会话。说实话,这真的非常甜蜜。请随时提出问题(或疑虑),因为我定期检查SO,我很乐意回复。

最新更新