Why can't you UnRegisterStartupScript?

10,983

Solution 1

I assume that you'd want to "unregister" the script (which has already been registered) under some condition, like so:

Page.ClientScript.RegisterStartupScript(this.GetType(), "KeyName", "alert('changed my mind')", true);
...
if(condition)
    Page.ClientScript.UnregisterStartupScript(this.GetType(), "KeyName", "alert('changed my mind')", true);

Why can't this simply be changed to:

if(!condition)
    Page.ClientScript.RegisterStartupScript(this.GetType(), "KeyName", "alert('changed my mind')", true);

Solution 2

It's actually worse than you think - "just re-registering it and having it do nothing" isn't an option either. The register method checks if a script is already registered with that key, and does nothing if it is. Once you call RegisterStartupScript, nothing you can do will stop that script being rendered.

As to why Microsoft did that, I'd guess that the possibility of changing or removing registered scripts was simply forgotten when RegisterStartupScript was first designed. The design choices happened to make it non-trivial to go back and create an unregister method, so they'd now need a good reason to do that.

When you register a script, it's stored in two places within the ClientScriptManager. A ListDictionary allows checks for whether a script is already registered, and an ArrayList stores the actual scripts as they will be rendered. I assume that the ArrayList is used to ensure that scripts are rendered in the order in which they were registered, but it also means that you can't tell which string in the ArrayList belongs to which key.

It wouldn't be terribly hard to equip your own page class with methods for MaybeAddStartupScript(key,script) and ChangedMyMindAboutThatStartupScript(key). Store the keys and scripts in your own dictionary and then in PreRender, register whichever scripts made it this far. It's certainly annoying to have to do it yourself, though.

Solution 3

After much studying, I found a solution to the problem if you want to only run the registered script once based on an event. Special thanks to @stevemegson's answer here that helped me understand what the problem actually was.

The solution involves the Sys.Application.add_load and remove_load javascript methods.

It works like this. A generic javascript function that first calls the worker function, then removes itself is the first statement, then add_load follows it up by calling that function:

protected void Button1_Click(object sender, EventArgs e)
{
    var script = @"<script language='javascript'>
                       function f(){ MyWorkerFunction(); 
                                     Sys.Application.remove_load(f);}; 
                       Sys.Application.add_load(f);
               </script>";

    ClientScript.RegisterStartupScript(GetType(), 
                                   "MyWorkerFunctionKey", 
                                    script, 
                                    false);
}

This is based on a telerik solution. It references telerik controls, but all the functionality is ASP.NET.

Share:
10,983

Related videos on Youtube

Lee Englestone
Author by

Lee Englestone

Lee is a passionate and innovative Developer and DevRel Lead whom excels at leadership, lateral thinking, new ideas/innovation and creating proof of concepts to realise their value. He is constantly experimenting with new technologies, exploring their benefits and introducing them to others including Augmented Reality, Machine Learning, and Artificial Intelligence. He also enjoys building useful resources for the tech community including http://VisualStudioTips.co.uk, http://XamarinARKit.com and http://TechCommunityCalendar.com You can follow him @LeeEnglestone

Updated on April 19, 2022

Comments

  • Lee Englestone
    Lee Englestone about 2 years

    Seems to me it is a bit wierd that you can do..

    Page.ClientScript.RegisterStartupScript(this.GetType(), "KeyName", "alert('changed my mind')", true);
    

    And then later on you can't unregister or stop the javascript from being rendered programatically.

    Why would Microsoft do this?

    I don't like the work around here.. http://hemant-vikram.blogspot.com/2005/11/unregister-startup-script-workaround.html

    And I don't like the option of just re-registering it and having it do nothing..

    Thoughts?

    • Ian Kemp
      Ian Kemp over 14 years
      Just out of interest's sake, why would you want to unregister a script?
  • Lee Englestone
    Lee Englestone over 14 years
    You're right instead of fixing the code smell with refactoring I was looking for a faster solution.. naughty!
  • Brian Hinchey
    Brian Hinchey over 14 years
    The key point I took from this answer was registering scripts in Pre_Render rather than registering in Page_Load and then attempting to re-register based on an event on the page.
  • crthompson
    crthompson about 10 years
    @BrianHinchey I agree, and while my answer here doesnt use prerender, it helps to understand what is going on behind the scenes. Take a look and tell me if you like my solution.
  • James Wierzba
    James Wierzba almost 8 years
    This still causes the script to run again on post back for me
  • crthompson
    crthompson almost 8 years
    @JamesWierzba Unless you are putting this in page load, this will execute then immediately unload this method. Perhaps you could duplicate your problem on a fiddle?