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服务器控件的所有好处获得大量功能。但我似乎无法找到任何关于在实践中使用这种技术的讨论,所以我想知道我可能会缺少什么。
答案 0 :(得分:2)
对于初学者,您向页面发送GET
请求,因此您要更新的控件将无法接收最新的表单数据。更重要的是,除非您的用户控件非常简单,否则ViewState将丢失,您可能不希望这样。
您可以使用POST
请求解决此问题,但还有其他潜在问题,例如你可以保证嵌入在你的用户控件中的客户端脚本能够再次运行,或者在所有浏览器上一致地更新它时不会运行吗?
幸运的是,others已经解决了这些问题。我建议您将用户控件放在客户端的UpdatePanel和force 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并运行它。在实践中,我很少做任何可怕的事情。我想如果你使用了很多重量控制器,这将是不切实际的,但在这种情况下你已经买了这个农场。