3

我的场景:

  • 我在UpdatePanel.
  • 我想组合我的脚本,所以我使用CompositeScriptin ScriptManager,并包括对WebUIValidation.js
  • 我正在使用 .NET 4.0

我的问题:

  • 当我异步更新面板时,.NET 在异步响应中加载WebUIValidation.js(在Scriptresource.axd文件中),即使它已在初始CompositeScript生成的脚本中加载。这是一个问题,因为我有自定义代码劫持了一些函数WebUIValidation.js,并且异步响应覆盖了我的劫持。
  • 如果将引用移至WebUIValidation.jsin ScriptsScriptManager则没有问题。
  • 如果您要拥有(我知道毫无意义)WebUIValidation.js中的唯一项目,CompositeScript那么就没有问题。
  • 这种异步重新加载不会发生在其他 .NET 库脚本中,例如WebForm.js

我想知道的:

  • WebUIValidation.js当异步响应已经包含在其中时,是否有理由将其加载到异步响应中CompositeScript

今天有人发布了一个类似(但不重复)的问题,并且正在转向说WebUIValidation.js可能无法由ScriptManager. 任何人都可以验证这一点吗?

要复制使用以下两个文件

test1.js

// To be added to the composite script
console.log('Test 1 Loaded');

测试.aspx

<%@ Page Language="vb" AutoEventWireup="false"  %>

<!DOCTYPE html>

<html>
<head runat="server">
    <title></title>
</head>
<body>
    <script language="VB" runat="server" runat="server">
        Protected Sub ButtonClicked(ByVal sender As Object, ByVal e As System.EventArgs) Handles TestButton.Click
            ButtonClickFeedback.Text = "Button clicked At " & Date.Now.ToString & "; Look at the scripts in your Developer Tools, there is now a separate script for WebUIValidation.js loaded, in spite of the composite script."
        End Sub 
    </script>

    <form runat="server">
        <asp:ScriptManager runat="server">
            <CompositeScript>
                <Scripts>
                    <asp:ScriptReference Path="~/test.js" />
                    <asp:ScriptReference Name="WebUIValidation.js" Assembly="System.Web" />
                </Scripts>
            </CompositeScript>
        </asp:ScriptManager>

        <h1>WebUIValidation.js, CompositeScript and UpdatePanel test</h1>

        <asp:UpdatePanel runat="server" ID="ButtonUpdatePanel">
            <ContentTemplate>
                <asp:Label runat="server" >This is a section with a validator that is within an UpdatePanel.  If you look at the scripts loaded, you will see the composite script in the detail.</asp:Label>
                <asp:Textbox ID="TestInputForValidator" runat="server" Text="This is populated so it will validate"/>
                <asp:RequiredFieldValidator runat="server" ControlToValidate="TestInputForValidator" ErrorMessage="You must write something" /><br />
                <asp:Button ID="TestButton" Text="Click Me!" runat="server"  /><br />
                <asp:Literal ID="ButtonClickFeedback" runat="server" />
            </ContentTemplate>
            <Triggers>
                <asp:AsyncPostBackTrigger ControlID="TestButton" />
            </Triggers>
        </asp:UpdatePanel>
    </form>
</body>
</html>

如果您使用开发人员工具检查正在加载哪些脚本,您应该会在单击按钮后看到一个额外的 Scriptresource.axd(包含 WebUIValidation.js)被加载,尽管存在带有 Scriptresource.axd 的复合脚本。test.js 只是一个示例 js 文件,用于模拟复合脚本的想法。

4

1 回答 1

0

分享我对为什么再次加载这些脚本(WebUIValidation.js 或 Focus.js)的调查。我现在刚刚发现了 Focus.js。

首先,http 请求的起源是在更新面板生成的部分更新中。如果您查看对异步 xhr POST 请求的响应,您会得到类似的结果。几乎在结尾处注意 ScriptResource.axd url。这是由客户端的 ajax 框架处理的,因为它是一个带有路径的脚本块,所以它被加载:

1|#||4|2999|updatePanel|ctl00_LoginContent_ctl00|
<div id="ctl00_LoginContent_...">[...html content here]</div>|
0|hiddenField|__LASTFOCUS||
0|hiddenField|__EVENTTARGET||
0|hiddenField|__EVENTARGUMENT||
904|hiddenField|__VIEWSTATE|UdWhNvH6wpBcPOigY[...]SIphbw==|
8|hiddenField|__VIEWSTATEGENERATOR|25748CED|
176|hiddenField|__EVENTVALIDATION|q+FUEVGVj+t[...]AzAm|
0|asyncPostBackControlIDs|||
0|postBackControlIDs|||
26|updatePanelIDs||tctl00$LoginContent$ctl00,|
0|childUpdatePanelIDs|||
25|panelsToRefreshIDs||ctl00$LoginContent$ctl00,|
2|asyncPostBackTimeout||90|
14|formAction||./Default.aspx|
119|scriptBlock|ScriptContentNoTags|function PopulateTimeZoneOffset(){[my own js here...]}|
154|scriptBlock|ScriptPath|/ScriptResource.axd?d=Uup1Lt[...]q450&t=ffffffffd4ee116f|
31|focus||ctl00_LoginContent_LoginControl|

现在调试服务器端代码,从https://referencesource.microsoft.com/加载 .net 程序集符号(使用此处描述的 VS 配置)。

页面请求管理器.cs

    private void ProcessFocus(HtmlTextWriter writer) {
        // Roughly stolen from Whidbey Page.cs
        if (_requireFocusScript) {
            Debug.Assert(ClientSupportsFocus, "If ClientSupportsFocus is false then we never should have set _requireFocusScript to true.");
            string focusedControlId = String.Empty;

            // Someone calling SetFocus(controlId) has the most precedent
            if (!String.IsNullOrEmpty(_focusedControlID)) {
                focusedControlId = _focusedControlID;
            }
            else {
                if (_focusedControl != null && _focusedControl.Visible) {
                    focusedControlId = _focusedControl.ClientID;
                }
            }
            if (focusedControlId.Length > 0) {
                // Register focus script library
                string focusResourceUrl = _owner.GetScriptResourceUrl("Focus.js", typeof(HtmlForm).Assembly);
                EncodeString(writer, ScriptBlockToken, "ScriptPath", focusResourceUrl); 
                // *********** THIS ENCODESTRING OUTPUTS THE PROBLEM !!!

                // Send the target control ID to the client
                EncodeString(writer, FocusToken, String.Empty, focusedControlId);
            }
        }
    }

我们深入 Page.ProcessRequest,现在在 Page.Render、RenderPageCallback 和 ProcessFocus 中。靠近末尾突出显示的 EncodeString 直接向编写器写入诸如“len|type|id|content|”之类的内容,包括writer.Write(content);where contentis "/ScriptResource.axd?d=Uup1IW...q450&t=ffffffffd4ee116f"。没有检查这个脚本是否已经注册到 ScriptManager,它没有调用 ScriptManager.RegisterXXXX。

所以在我看来,这就是为已经加载的内容获取另一个 http 请求的原因。ProcessFocus 是作为“渲染”的一部分完成的,使用任何 ScriptManager 功能都为时已晚。

我想不出避免这个http请求的方法(除了不使用SetFocus.net框架中的任何类型的东西)。

(运行VS 2015,.net framework 4.6.2,ajax control toolkit 17.1)

于 2017-05-19T07:28:24.673 回答