2

在过去的几周里,我一直在旅途中,试图找出一个拥有大量基础设施的非常古老的应用程序中的大量缺陷。它使用了多个 3rd 方控件,我不可能希望在我拥有的时间范围内修复这些控件。这些缺陷之一归结为客户端状态的多个 javascript 模型。具体来说,一些控件希望能够挂钩到 jQuery 表单提交事件,而其他控件则在原始 .NET 中工作(theForm.onsubmit直接覆盖1),还有一些控件使用Sys.WebForms和注册事件处理程序PageRequestManager(在某些页面上)。

起初我以为我可以简单地__doPostBack向页面添加一个新函数,但我无法(有时)注入它以在标准函数和Sys.WebForms运行拦截的代码之间运行__doPostBack。如果我之后覆盖它,那么我要么无法触发 WebForms 内部的逻辑,要么无法触发 jQuery 事件。我可以在原始函数之前注入它,__doPostBack但是如果不禁用原始函数被添加到页面,那什么也做不了。所以我想出了以下代码。

如果这是我实际尝试的唯一方法,为什么我还没有在网上找到它?有一个更好的方法吗?

public class Form : System.Web.UI.HtmlControls.HtmlForm 
{
    const string DoPostBackFn = @"
    <script type=""text/javascript"">
    (function ($) {
        window.theForm = document.forms[0];
        window.__doPostBack = function (eventTarget, eventArgument) {
            var originalvalues = [
                theForm.__EVENTTARGET.value,
                theForm.__EVENTARGUMENT.value,
                theForm.onsubmit
            ];
            if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
                theForm.__EVENTTARGET.value = eventTarget;
                theForm.__EVENTARGUMENT.value = eventArgument;
                try {
                    theForm.onsubmit = null;
                    $(theForm).submit();
                } finally {
                    theForm.__EVENTTARGET.value = originalvalues[0];
                    theForm.__EVENTARGUMENT.value = originalvalues[1];
                    theForm.onsubmit = originalvalues[2];
                }
            }
        };
    }(jQuery));
    </script>";

    protected override void RenderChildren(HtmlTextWriter writer) 
    {
        //temporarily disable the page from rendering the postback script
        var fRequirePostBackScript = typeof(System.Web.UI.Page).GetField("_fRequirePostBackScript", BindingFlags.Instance | BindingFlags.NonPublic);
        var isPostBackRequired = (bool)fRequirePostBackScript.GetValue(Page);
        if (isPostBackRequired) 
        {
            fRequirePostBackScript.SetValue(Page, false);

            //write custom postback script
            writer.Write(DoPostBackFn);
            //tell the page that the script is rendered already
            typeof(System.Web.UI.Page).GetField("_fPostBackScriptRendered", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(Page, true);
        }

        //let ASP.NET do its thing
        base.RenderChildren(writer);

        //reset field to original value
        fRequirePostBackScript.SetValue(Page, isPostBackRequired);
    }
}

1这是你在页面上时显然不能做的事情,Sys.WebForms因为它盲目地覆盖 DOM 事件而不考虑已经注册的内容(至少在这个版本中),所以我必须在其他地方对它们做一些事情

4

0 回答 0