call JavaScript - jQuery code from ASP.NET Server-Side

by Arnold Matusz 3 6 2009

jQuery got so close to me lately that I can see myself adding the scripts to my project almost unconsciously. The thing is, jQuery is very useful for me, in almost all situations and it has been a do or die enhancement for all my project since I first put my hands on it.

Of course while using it, you encounter few situations which need a bit of research to solve, mostly when you are trying to combine it with some other technologies like: UpdatePanels and ASP.NET Ajax. For instance there are many situations when I would like to run some jQuery magic based on some decision that I make on the server side.

It’s not the case to use jQuery ajax calls here, the point is I would like to run some jQuery code after a postback or an asynchronous postback with results coming from the server. This would mean that I’d need to prepare the scripts on the server-side in my code-behind and use RegisterClientScriptBlock to run them on the browser.

The catch is that using ClientScript.RegisterClientScriptBlock simply won’t render your scripts when the request is coming from an AsyncPostbackTrigger of an UpdatePanel. In this case you’ll need to call ScriptManager.RegisterClientScriptBlock.

To solve this automatically I’ve created a method which then handles all the logic that I need for running some JavaScript code after the request has been processed. This method the JavaScript code that needs to run on the browser as a parameter, and encloses within a $(document).ready for sake of this example.

The whole logic sits behind this idea: We need to know if the current request is a standard synchronous Postback or if it is an AJAX Asynchronous Postback from an UpdatePanel. Therefore in my code I check if there is any ScriptManager registered with the Page (in this case ScriptManager.GetCurrent(this), ScriptManager.GetCurrent(Page) will not return null, but we still need to check whether the request was asynchronous by checking the IsAsynchPostback on the ScriptManager instance.

If there is a ScriptManager on the page and the request was Asynchronous, then the JavaScript code needs to be registered with ScriptManager.RegisterClientScriptBlock. If the request is just a simple standard Postback, registering the JavaScript with Page.ClientScript.RegisterClientScriptBlock is the solution.

For sake of this post I’ve created a short example (which you can also download and view at: )

    private string getjQueryCode(string jsCodetoRun)
    {
        StringBuilder sb = new StringBuilder();
        sb.AppendLine("$(document).ready(function() {");
        sb.AppendLine(jsCodetoRun);
        sb.AppendLine(" });");

        return sb.ToString();
    }

getjQueryCode is the method that encloses your code that needs to run after the Postback within a jQuery $(document).ready() call.

    private void runjQueryCode(string jsCodetoRun)
    {

        ScriptManager requestSM = ScriptManager.GetCurrent(this);
        if (requestSM != null && requestSM.IsInAsyncPostBack)
        {
            ScriptManager.RegisterClientScriptBlock(this, 
                                                    typeof(Page), 
                                                    Guid.NewGuid().ToString(), 
                                                    getjQueryCode(jsCodetoRun), 
                                                    true);
        }
        else
        {
            ClientScript.RegisterClientScriptBlock(typeof(Page), 
                                                   Guid.NewGuid().ToString(), 
                                                   getjQueryCode(jsCodetoRun), 
                                                   true);
        }
    }

runjQueryCode is the method which handles the logic I talked about earlier. By using this function all over you project respects the DRY principle, of course you can change the way it generates the JavaScript code on the server side, I have created this only for sake of this example.

The markup that is needed for this example is the following:

    <asp:ScriptManager ID="sm" runat="server">
    </asp:ScriptManager>
    <asp:UpdatePanel ID="upPnl" runat="server">
        <ContentTemplate>
            <asp:Button ID="btnPostback" runat="server" 
                        Text="Standard Postback" 
                        OnClick="btnPostback_Click" />
            <asp:Button ID="btnAsynchPostback" runat="server" 
                        Text="Asynchronous Postback" 
                        OnClick="btnAsynchPostback_Click" />
        </ContentTemplate>
        <Triggers>
            <asp:PostBackTrigger ControlID="btnPostback" />
        </Triggers>
    </asp:UpdatePanel>

Please note how the first button is set as a PostBackTrigger. This will force it to reload the whole page (which in term demonstrates how the code works when there is a standard postback) even if it is declared within the UpdatePanel. The second button launches an AJAX request (which in term demonstrates how the runjQueryCode method works while fulfilling and AJAX request).

    protected void btnPostback_Click(object sender, EventArgs e)
    {
        runjQueryCode("alert('After a standard postback.')");
    }

    protected void btnAsynchPostback_Click(object sender, EventArgs e)
    {
        runjQueryCode("alert('After an asynchronous postback.')");
    }

The click event handlers of the 2 buttons on the form simply call the runjQueryCode method with custom JavaScript code (in this case it’s a simple JavaScript alert).

One very important thing to note is the following:
The rendered script tag needs to be after the script tag that imports the jQuery library. If you use <Scripts> Collection from the ScriptManager, this could break the code because your scripts from the server side will get rendered before the ScriptManager renders the script tags for the js files you use with the ScriptManager.
One workaround is: add the script tags in the <head> section of your page.

As a little homework, if anybody is interested, to check that your JavaScript code won’t run after an ASP.NET AJAX request, you can create a Button in an UpdatePanel, and on its click event try to run the ClientScript.RegisterClientScriptBlock and miraculously nothing will happen.

Download the code or check out the Demo
DZone it Digg it Submit to StumbleUpon Submit to Technorati Submit to reddit.com Submit to del.icio.us Submit to NewsVine Submit to Furl Submit to BlinkList

Tags: , , , ,

jQuery | C# | ASP.NET | JavaScript

Comments

6/4/2009 12:12:33 AM #

trackback

run jQuery code from ASP.NET Server-Side

You've been kicked (a good thing) - Trackback from DotNetKicks.com

DotNetKicks.com |

6/4/2009 12:12:49 AM #

trackback

run jQuery code from ASP.NET Server-Side

You are voted (great) - Trackback from Web Development Community

Web Development Community |

6/4/2009 6:00:38 AM #

trackback

run jQuery code from ASP.NET Server-Side | Arnold Matusz's Blog

Thank you for submitting this cool story - Trackback from DotNetShoutout

DotNetShoutout |

8/17/2009 7:51:17 AM #

Leona

You saved me tons of research time.  This is so much better that those ajax tool extenders which I don't appreciate as much as JQuery.  I just did a simple show/hide JQuery call, which works great and so easy to use.  I'm going to venture out and call more extensive jquery functions.  Thank you for the code, now I'm more empowered to use jquery more often in my c# .net programming.  

I did try to put your methods in a class to use throughout my application, but the class complain that the scriptmanager "ScriptManager.GetCurrent(this)" overload method has invalid argument.  Looks like it does not like the "this".  Any suggestion?  If I want to use your method in a class, I need to pass the entire page to the method?  How would I do that?  runjQueryCode(string jsCodetoRun, Page myPage)?

Thanks again.

Leona United States |

8/25/2009 2:30:15 PM #

NNKHO

Excelente!! Muy buen artículo y funcional.

NNKHO Mexico |

1/6/2010 7:31:48 AM #

Ricardo

thanks great help

Ricardo Mexico |

5/30/2010 4:36:25 PM #

Campo

This maybe helpful for other people, we were using  <Scripts> Collection from the ScriptManager, so we had to change from "RegisterClientScriptBlock" to "RegisterStartupScript".  Great article, thanks for posting!!

Campo

Campo Australia |