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, имитирующий идею составных скриптов.
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 framework).
(Запуск VS 2015, .net Framework 4.6.2, инструментарий управления ajax 17.1)