Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I overwrite a Javascript function added (dynamically) by Asp.Net UpdatePanel?

I'm having a bit of trouble with what I can only imagine is a Javascript scope problem alongside with Microsoft Asp.Net client side framework.

Because of the reasons stated on this question I need to overwrite the javascript function ValidatorConvert, served by Asp.Net's ScriptResource.axd and used by its Validator server controls.

First I will present how I can make the code work. Then I'll show a scenario where I can't make it work.

Here's a simple Asp.Net WebForm with a validator control:

<body>
<form id="form1" runat="server">
    <script type="text/javascript">
        function ValidatorConvert(op, dataType, val) {
            //>>Overwrite ValidatorConvert function.
            //>>Call to the original JS file will be below the form tag and above script tag
            return op.toString(); //<<Consider everything as valid (client side)
        }
    </script>
    <asp:ScriptManager runat="server"
        ID="Scriptmanager1" 
        allowcustomerrorsredirect="true" 
        asyncpostbackerrormessage="Operation cannot be executed."
        asyncpostbacktimeout="90"
        enablepartialrendering="true"
        enablescriptglobalization="true" 
        enablescriptlocalization="true" 
        supportspartialrendering="true" 
        scriptmode="Inherit"></asp:ScriptManager>
    <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
    <asp:CompareValidator
        ID="CompareValidator1"
        runat="server"
        ErrorMessage="Ops, not an integer"
        Operator="DataTypeCheck"
        Type="Integer"
        ControlToValidate="TextBox1"></asp:CompareValidator>
    <asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" />
</form>
</body>

Now, when asp.net renders the form, it will somehow detect that there is a validator control visible on the page. Because of that there will be a call to the client side JS for validators right below the form and right above my script tag. This JS file will have a ValidatorConvert function which will be overwritten by mine.

Now, here's a scenario where this won't work. Here's a slightly different WebForm:

<body>
<form id="form1" runat="server">
    <asp:ScriptManager runat="server"
        ID="Scriptmanager1" 
        allowcustomerrorsredirect="true" 
        asyncpostbackerrormessage="Operation cannot be executed."
        asyncpostbacktimeout="90"
        enablepartialrendering="true"
        enablescriptglobalization="true" 
        enablescriptlocalization="true" 
        supportspartialrendering="true" 
        scriptmode="Inherit"></asp:ScriptManager>
    <asp:UpdatePanel ID="UpdatePanel1" runat="server">
        <ContentTemplate>
            <asp:MultiView ID="MultiView1" runat="server" ActiveViewIndex="0">
                <asp:View ID="View1" runat="server">
                    <asp:Button ID="ButtonShowInput" runat="server" Text="Show Input     Field" CausesValidation="false" OnClick="ButtonShowInput_Click" />
                </asp:View>
                <asp:View ID="View2" runat="server">
                    <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
                    <asp:CompareValidator
                        ID="CompareValidator1"
                        runat="server"
                        ErrorMessage="Ops, not an integer"
                        Operator="DataTypeCheck"
                        Type="Integer"
                        ControlToValidate="TextBox1"></asp:CompareValidator>
                    <asp:Button ID="Button1" runat="server" Text="Button"   OnClick="Button1_Click" />
                </asp:View>
            </asp:MultiView>
        </ContentTemplate>
    </asp:UpdatePanel>
</form>
</body>

Now I have a MultiView inside an UpdatePanel. The view visible when the page load is the first one with only a button. When this button is pressed, it will display the second view with the validator control. Because this is inside an UpdateUpdate, this will be done using AJAX.

Now, when the form is rendered the validator control is not visible by default. So, the link to the javascript file (ScriptResource.axd) will not be placed on the page at all!

But when the button is pressed and the validator is visible, the link will be added dinamically.

The problem is, this link is placed by the asp.net framework in the head tag.

And even though my function is still defined hierarchically below the original one, my function is not called.

I tried placing my function in different places, including the head tag, but it doesn't seem to work either. It seems like it is considered as valid the last defined function.

So, how can I overwrite the function on this second scenario? Furthermore, is there a single solution that will work for both scenarios?

Thanks in advance for taking the time.

like image 412
Rodrigo Lira Avatar asked Nov 02 '22 10:11

Rodrigo Lira


1 Answers

Thanks to Yuriy's input, I was able to come up with a solution.

Basically, I created code that will define my function when the page first load. Also, I registered my custom function to redefine my function after every ajax request. Given that I put this code on a MasterPage I'm able to make it work across all the application.

Here's the code:

MasterPage.aspx is a simple Html page with its ContentPlaceHolders and the ScriptManager right below the form tag. Also, I had to place a reference to my "Utils.js" at the top of the page (head tag).

MasterPage.aspx.cs

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        if (!Page.ClientScript.IsStartupScriptRegistered("jsDefineFunction"))
            Page.ClientScript.RegisterStartupScript(Page.GetType(), "jsDefineFunction", "defineValidationFunction();", true);

        if (!Page.ClientScript.IsStartupScriptRegistered("jsDefineEndRequestFunction"))
            Page.ClientScript.RegisterStartupScript(Page.GetType(), "jsDefineEndRequestFunction", "Sys.WebForms.PageRequestManager.getInstance().add_endRequest(defineValidationFunction);", true);
    }
}

Utils.js

function defineValidationFunction() {
    var ValidatorConvert = function (op, dataType, val) {
            //>>Consider everything as valid (client side)
            return op.toString();
        }
}

With that in place, my code works for all pages that uses the MasterPage. The code will constantly overwrite the validation function with mine. There's a little bit of overhead but I couldn't figure out another way.

like image 157
Rodrigo Lira Avatar answered Nov 14 '22 04:11

Rodrigo Lira