使用ajax更新ASP.NET服务器呈现的控件

时间:2010-10-28 17:25:52

标签: c# asp.net jquery ajax

This question让我思考如何做一个相对可撤销的事情:从ASP.NET无缝集成服务器生成的HTML和通过javascript进行客户端控制。当然,您始终可以使用javascript / jquery / libraries来创建相同的显示客户端。但在大多数情况下,更容易在服务器上进行所有渲染,而不是仅仅将数据传递给必须处理用户界面和渲染的客户端控件。或许你已经有了很多交互性较低的服务器代码,你真的不想完全重新使用javascript库来添加更好的交互性。

我有一个似乎在基本的概念证明中起作用的理论。假设您希望基于客户端事件完全重新呈现服务器生成的控件的HTML,而不进行回发。所以使用jquery,我有一个页面:

    default.aspx:
   <a id="link1" href="#">Click Here</a>
   <div id="container">
   <asp:PlaceHolder id="MyPlaceholder" runat="server" />
   </div>
    <script type="text/javascript">
        $(document).ready(function() {
            $('#link1').click(function() {
                $.ajax({
                    url: "default.aspx",
                    type: "GET",
                    dataType: "html",
                    async: true,
                    data: { "ajax": "1" },
                    success: function(obj) {
                    // replace the HTML
                        $('#container').html(obj);
                    }
                });
            });
        });

该事件导致它使用ajax查询自身。做诡计的代码隐藏是这样的:

    TestUserControl ctl;
    string ajax;
    protected void Page_Load(object sender, EventArgs e)
    {
        ctl = (TestUserControl)Page.LoadControl("TestUserControl.ascx");
        Myplaceholder.Controls.Add(ctl);
        ctl.OnRender += new TestuserControl.RenderHandler(ctl_Render);
    }
    protected void Page_PreRender()
    {
        ajax = Request.QueryString["ajax"] == null ? "" : Request.QueryString["ajax"];
    }
    void ctl_Render()
    {
        if (ajax == "1")
        {
            StringBuilder sb = new StringBuilder();
            StringWriter sw = new StringWriter(sb);

            using (HtmlTextWriter writer = new HtmlTextWriter(sw))
            {
                ctl.DoRender(writer);
            }

            Response.Write(sb.ToString());
            Response.End();
        }
    }

在TestUserControl中,我公开base.render以获取输出:

   public void DoRender(HtmlTextWriter writer)
    {
        base.Render(writer);
    }

基本上,如果在没有“ajax”查询字符串的情况下调用页面,它就像自己一样。但是当使用该查询字符串时,它会拦截我所关注的内容(一个名为TestUserControl.ascx的用户控件)的输出流,并呈现就是。这将返回给客户端,客户端会更新HTML。所有的ID都将像以前一样完全重新创建,因为我不是试图单独呈现该控件,而是在其自己的页面的上下文中。从理论上讲,ASP.NET创建的每一个魔法都应该通过ajax查询进行复制,检索和更新。

除了明显缺乏效率之外,它似乎在这个小小的测试中游泳。我可以使用服务器生成的HTML完全重新呈现控件,而无需回发,我写了零javascript。此示例实际上并未更改任何内容,但传递更多参数以更改输出会很简单。

我想知道是否有人在实践中尝试过这样的事情?我可能没有想到哪些潜在的问题?

如果服务器性能不是问题,那么看起来很容易通过ASP.NET服务器控件的所有好处获得大量功能。但我似乎无法找到任何关于在实践中使用这种技术的讨论,所以我想知道我可能会缺少什么。

3 个答案:

答案 0 :(得分:2)

对于初学者,您向页面发送GET请求,因此您要更新的控件将无法接收最新的表单数据。更重要的是,除非您的用户控件非常简单,否则ViewState将丢失,您可能不希望这样。

您可以使用POST请求解决此问题,但还有其他潜在问题,例如你可以保证嵌入在你的用户控件中的客户端脚本能够再次运行,或者在所有浏览器上一致地更新它时不会运行吗?

幸运的是,others已经解决了这些问题。我建议您将用户控件放在客户端的UpdatePanelforce a refresh内:

__doPostBack("yourUpdatePanelClientID", "");

答案 1 :(得分:0)

如果替代方案使用的是UpdatePanel,那么考虑部分渲染绝对值得。即使您只使用UpdatePanel更新页面的一小部分,这些更新也必须将整个ViewState发送回服务器,服务器必须run the entire page through its life cycle,呈现它,然后提取部分区域。为方便起见,您需要a significant performance hit

在您的情况下,由于您在ASPX pae中呈现部分内容,因此您仍然会遇到页面生命周期。它没有UpdatePanel那么糟糕,但不必要。

我发现splitting the partial rendering out to a web service or HttpHandler handler效果很好。它比其他大多数用于在WebForms中渲染部分的方法更快 ,但仍然允许使用用户控件进行模板化的灵活性。

缺点是用户控件内的控件无法处理PostBack。你绝对可以重新渲染它和/或传递参数来控制它的渲染,但是你不能使用它来渲染GridView并期望它的分页链接能够工作,例如。

答案 2 :(得分:0)

我希望有更多关于将ASP.NET Web表单移动到现代时代的讨论。我必须自己弄清楚大多数事情。我个人努力寻求最简单的解决方案,并避免所有需要在更多Microsoft上进行分层的解决方案。没有什么能比MS,我只想保持简单并使用普通的网络标准。

到目前为止,我已经能够使用jQuery加载AJAX了解我尝试过的所有内容。没有轻拍,简单的答案,但如果你坚持不懈,你可以解决因旧学校ASP.NET实践导致的任何客户端问题。

我认为最重要的事情是停止使用ViewState。完全。这将迫使您摆脱许多可能导致您在客户端出现问题的可怕做法。这实际上比你想象的要容易。在这一点上,AJAXing的东西通常会起作用。甚至DataGrids。做自己的分页,无论是客户端还是服务器端,都不是那么难,然后你可以在任何地方重用你的解决方案。

问题将来自您无法控制的第三方内容。在这些情况下,您可以使用IE开发人员工具(F12)来查看ASP.NET最初发送的内容。最糟糕的情况是,你必须自己编写一些JavaScript并运行它。在实践中,我很少做任何可怕的事情。我想如果你使用了很多重量控制器,这将是不切实际的,但在这种情况下你已经买了这个农场。