Asp.net WebUIValidation.js在CompositeScript和UpdatePanel中时会在异步调用中重新加载

Asp.net WebUIValidation.js在CompositeScript和UpdatePanel中时会在异步调用中重新加载,asp.net,updatepanel,scriptmanager,scriptresource.axd,Asp.net,Updatepanel,Scriptmanager,Scriptresource.axd,我的场景: 我在UpdatePanel中有一个验证器 我想合并我的脚本,因此我在ScriptManager中使用CompositeScript,并包含对WebUIValidation.js 我正在使用.NET4.0 我的问题: 当我异步更新异步响应中的面板时,.NET加载WebUIValidation.js(在Scriptresource.axd文件中),即使它已加载到初始CompositeScript生成的脚本中。这是一个问题,因为我的自定义代码劫持了WebUIValidation.js

我的场景:

  • 我在
    UpdatePanel
    中有一个验证器
  • 我想合并我的脚本,因此我在
    ScriptManager
    中使用
    CompositeScript
    ,并包含对
    WebUIValidation.js
  • 我正在使用.NET4.0
我的问题:

  • 当我异步更新异步响应中的面板时,.NET加载
    WebUIValidation.js
    (在
    Scriptresource.axd
    文件中),即使它已加载到初始
    CompositeScript
    生成的脚本中。这是一个问题,因为我的自定义代码劫持了
    WebUIValidation.js
    中的一些函数,而异步响应会覆盖我的劫持
  • 如果将
    ScriptManager
    中对
    WebUIValidation.js
    的引用移动到
    Scripts
    ,则没有问题
  • 如果将
    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');
    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);
            }
        }
    }
test.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>

受保护的子按钮单击(ByVal sender作为对象,ByVal e作为System.EventArgs)处理TestButton。单击
ButtonClickFeedback.Text=“Button clicked At”&Date.Now.ToString&“查看开发人员工具中的脚本,现在已为WebUIValidation.js加载了一个单独的脚本,尽管使用了复合脚本。”
端接头
WebUIValidation.js、CompositeScript和UpdatePanel测试
这是UpdatePanel中包含验证器的部分。如果查看加载的脚本,您将看到详细的复合脚本。



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

分享我对为什么再次加载这些脚本的调查(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|
我们深入了解了Page.ProcessRequest,现在又深入到Page.Render、RenderPageCallback和ProcessFocus。结尾附近突出显示的EncodeString直接写入写入程序,例如“len | type | id | content |”,包括
writer.Write(content)其中
内容
“/ScriptResource.axd?d=Uup1IW…q450&t=ffffffffffd4ee116f”
。没有检查此脚本是否已向ScriptManager注册,它没有调用ScriptManager.RegisterXXXX

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

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


(运行VS 2015、.net framework 4.6.2、ajax控制工具包17.1)

@alerygy:您有没有回避过这个问题?我今天也遇到了类似的问题。@TCM-我能够解决这个问题的唯一方法是将WebUIValidation.js移动到
ScriptManager
部分,而不是在
CompositeScripts
下-这意味着我有两个脚本调用(ScriptResource.axd中的composite和单个WebUIValidation)在网页上。不太理想,但问题似乎在于WebUIValidation.js的管理方式。@alergy我也遇到了同样的问题,但将
WebUIValidation.js
移动到
Script
部分,而不使用
CompositeScripts
,因为父级并没有解决问题。在部分回发后,
ScriptResource.axd
仍然被加载,因此我覆盖的验证函数将丢失。我得到了Focus.js(以及WebUIValidation.js)的相同内容