WebUIValidation.js перезагружается в асинхронных вызовах в CompositeScript и UpdatePanel

Мой сценарий:

  • У меня есть валидатор в UpdatePanel.
  • Я хочу объединить свои сценарии, поэтому я использую CompositeScript в ScriptManager и включаю ссылку на WebUIValidation.js
  • Я использую .NET 4.0

Моя проблема:

  • Когда я асинхронно обновляю панель, .NET загружает WebUIValidation.js (в файле Scriptresource.axd) в асинхронный ответ, даже если он был загружен в начальном CompositeScript-сгенерированном скрипте. Это проблема, потому что у меня есть собственный код, который перехватывает некоторые функции в WebUIValidation.js, а асинхронный ответ отменяет мои взломы.
  • Если вы переместите ссылку с WebUIValidation.js на Scripts в ScriptManager, проблем не будет.
  • Если бы у вас был 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');

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>

Если вы используете инструменты разработчика для проверки того, какие скрипты загружаются, вы должны увидеть дополнительный Scriptresource.axd (содержащий WebUIValidation.js), загружаемый после нажатия кнопки, несмотря на существование Scriptresource.axd с составной скрипт. test.js - это просто образец js-файла, имитирующий идею составных скриптов.


person alergy    schedule 08.01.2014    source источник
comment
@alerygy: Вы когда-нибудь обходили эту проблему? Сегодня я столкнулся с этой похожей проблемой.   -  person TCM    schedule 15.05.2014
comment
@TCM - единственный способ обойти эту проблему - переместить WebUIValidation.js в раздел <Scripts> ScriptManager, а не в CompositeScripts - это означает, что у меня есть два вызова сценария (составной и отдельный WebUIValidation в ScriptResource. axd) на веб-странице. Не идеально, но, похоже, проблема заключается в самом способе управления WebUIValidation.js.   -  person alergy    schedule 15.05.2014
comment
@alegery У меня та же проблема, но перемещение WebUIValidation.js в раздел Script без CompositeScripts в качестве родителя не решило проблему. ScriptResource.axd все еще загружается после частичной обратной передачи, поэтому мои переопределенные функции проверки будут потеряны.   -  person Martin Braun    schedule 21.11.2016
comment
Я получаю то же самое с Focus.js (а также с WebUIValidation.js)   -  person Thierry_S    schedule 18.05.2017


Ответы (1)


Поделюсь своим исследованием, почему он снова загружает эти скрипты (WebUIValidation.js или Focus.js). Я только что нашел о Focus.js.

Во-первых, запрос http возникает в частичном обновлении, сгенерированном панелью обновлений. Если вы посмотрите на ответ на асинхронный запрос xhr POST, у вас будет что-то вроде этого. Обратите внимание почти на конец URL-адреса ScriptResource.axd. Это обрабатывается фреймворком 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|

Теперь отлаживаем код на стороне сервера, загружая символы сборок .net из https://referencesource.microsoft.com/ (с конфигурацией VS, как описано там).

PageRequestmanager.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);, где content - это "/ScriptResource.axd?d=Uup1IW...q450&t=ffffffffd4ee116f". Нет проверки, зарегистрирован ли этот сценарий в ScriptManager, он не вызывает ScriptManager.RegisterXXXX.

Мне кажется, что это причина получения другого HTTP-запроса для чего-то, что уже загружено. ProcessFocus выполняется как часть «Render», но уже слишком поздно, чтобы использовать какие-либо функции ScriptManager.

Я не могу придумать, как избежать этого HTTP-запроса (кроме того, что я не использую какие-либо вещи типа SetFocus из инфраструктуры .net).

(Запуск VS 2015, .NET framework 4.6.2, набор инструментов управления ajax 17.1)

person Thierry_S    schedule 19.05.2017