WebUIValidation.js gets reloaded in async calls when in CompositeScript and UpdatePanel

旧街凉风 提交于 2019-12-04 14:23:54

Sharing my investigation on why it's loading these scripts again (WebUIValidation.js or Focus.js). I've just found about Focus.js for now.

First, the origination of the http request is in the partial update generated by the update panel. If you look at the reponse to the asynchronous xhr POST request, you'll have something like this. Note almost at the end the ScriptResource.axd url. This is processed by the ajax framework on the client side and since it's a script block with a path, it gets loaded:

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|

Now debugging server side code, loading the .net assemblies symbols from https://referencesource.microsoft.com/ (with VS configuration as described there).

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);
            }
        }
    }

We are deep inside Page.ProcessRequest, and now in Page.Render, RenderPageCallback and ProcessFocus. The highlighted EncodeString near the end writes directly to the writer things like "len|type|id|content|", including writer.Write(content); where content is "/ScriptResource.axd?d=Uup1IW...q450&t=ffffffffd4ee116f". There is no check to see if this script is already registered with the ScriptManager, it's not calling ScriptManager.RegisterXXXX.

So it seems to me that's the cause of getting another http request for something that's already loaded. ProcessFocus is done as part of "Render", far too late to use any ScriptManager functinality.

I can't think of a way to avoid this http request (apart from not using any SetFocus type thing from the .net framework).

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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!