Click here to Skip to main content
Click here to Skip to main content

How to post back to the server using JavaScript in ASP.NET

, 8 Sep 2009 CDDL
Rate this:
Please Sign up or sign in to vote.
This article describes how to create postbacks to the server without resorting to the built-in function __doPostBack.

Introduction

I, like many of you, have had a need from time to time to create a postback in ASP.NET using JavaScript. When I searched for a solution online, I found many posts advocating the use of __doPostBack, Microsoft's JavaScript function created to post back to the server. There are several problems with this, however, including:

  1. It is not documented by Microsoft, so it might not be supported in future versions.
  2. It skips client-side validation by the ASP.NET validators.
  3. It doesn't work with UpdatePanels in ASP.NET AJAX.

You can get around the second and third items on the list without too much difficulty, if you're willing to duplicate Microsoft's code in your own functions, and write even more code that may or may not be supported by Microsoft in future versions. However, there is a little-known object available in the .NET framework called "PostBackOptions" that is worth discussing. It is a little bit of a pain to use, so I have wrapped it in a custom control in order to limit the amount of manual coding necessary to use the object.

Using the Code

Control Properties

  • CausesValidation - Just like a button, this specifies whether a call to this function causes the page to be validated.
  • ValidationGroup - Just like a button, this specifies an optional validation group.
  • FunctionName - This is the JavaScript function that will be called in order to post back to the server.
  • JavaScriptNamespaces - This is a list of namespaces that help prevent function name collisions.
  • Postback - This is a delegate that allows you to run code when the postback code is called.
  • PostbackButton - This is a private button that the user won't see, but is necessary for PostBackOptions to work.

JavaScriptNamespaces

Before we get to the code itself, I may need to explain a bit of unconventional JavaScript usage. Writing maintainable, readable code should be important to every programmer of every language, and writing JavaScript should be no different. A full explanation of writing maintainable JavaScript is beyond the scope of this article, but I strongly suggest simulating namespaces in your code to prevent name clashes and to better organize your functions. I do so here, so a bit of an explanation may be necessary. In order to make this happen, here's the code I wrote for the control:

public class JavaScriptPostback : CompositeControl
{
    //Property declarations here
    //CompositeControl overrides here

    protected override void Render(HtmlTextWriter writer)
    {
        //Code to create a PostBackOptions object called "options" should go here

        String functionName = JavaScriptNamespaces.Equals(String.Empty) ? 
          FunctionName : String.Concat(JavaScriptNamespaces, ".", FunctionName);
        writer.Write("<script type='text/javascript'>");
        AddNamespaces(JavaScriptNamespaces, writer);
        writer.Write(String.Format("{0} = function() {1}", functionName, "{"));
        writer.Write(this.Page.ClientScript.GetPostBackEventReference(options));
        writer.Write("};");
        writer.Write("</script>");
    }

    private void AddNamespaces(String originalNamespaces, 
                 System.Web.UI.HtmlTextWriter output)
    {
        StringBuilder namespaces = new StringBuilder();
        if (!originalNamespaces.Equals(String.Empty))
        {
            String[] namespaceList = originalNamespaces.Split('.');
            foreach (String nspace in namespaceList)
            {
                if (namespaces.Length > 0)
                    namespaces.Append(".");

                namespaces.Append(nspace);

                output.WriteLine(String.Concat("if (typeof(", 
                    namespaces.ToString(), ") === 'undefined') { ", 
                    namespaces.ToString(), " = {}; }"));
            }
        }
    }
}

If I were to use "MyCompany.Custom" as my JavaScriptNamespaces, and "PostBack" as my FunctionName, this JavaScript would be rendered on the page:

<script type='text/javascript'>
if (typeof(MyCompany) === 'undefined')
    MyCompany = {};
if (typeof(MyCompany.Custom) === 'undefined')
    MyCompany.Custom = {};
if (typeof(MyCompany.Custom.PostBack) === 'undefined')
    MyCompany.Custom.PostBack = function()
     { /* code generated by PostBackOptions would go here */ };
</script>

What's happening here? I check for the existence of an object called "MyCompany", and if it doesn't exist, I created it as an (empty) object to serve as a container for the other "namespaces" and functions. The same thing happens for "MyCompany.Custom". After checking for the existence of "MyCompany.Custom.PostBack", I create and assign an "anonymous function" to that object. In order to call the function, you can just call "MyCompany.Custom.PostBack()". For a more thorough explanation, please consult David Flanagan's book on JavaScript, called "JavaScript: A Definitive Guide", published by O'Reilly. This is one of the few books I've seen that describes how to use the language rather than simply telling you what's available.

CompositeControl

The custom control inherits from CompositeControl, since a button and some custom JavaScript are both part of the control. I could have made this control inherit from the Button class instead, and overridden Render() to also render the necessary JavaScript, but there would have been a lot of properties available to the control that would be useless to the user, so I chose to use CompositeControl instead. For further information about the CompositeControl, please consult Microsoft's documentation.

PostBackOptions

Here is the remaining code in Render():

protected override void Render(HtmlTextWriter writer)
{
    base.Render(writer);
    PostBackOptions options = new PostBackOptions(PostbackButton);
    options.PerformValidation = this.CausesValidation;
    options.ValidationGroup = this.ValidationGroup;
    this.Page.ClientScript.RegisterForEventValidation(options);
}

There really isn't much needed to use the class. It needs to know what validation options you are using, and the code:

this.Page.ClientScript.GetPostBackEventReference(options);

returns a JavaScript function that will post back to the server.

It is important to note that calling base.Render(writer) isn't strictly necessary. The reason I do so is to render the button on the page, which allows the UpdatePanel to find the control.

Handling the Postback

Now we need the ability to specify what happens when the control of the application returns to the server. We can do that by creating a delegate:

public event EventHandler Postback;
void PostbackButton_Click(object sender, EventArgs e)
{
    if (Postback != null)
        Postback(sender, e);
}

When we create the PostBackOptions object, we pass in a private PostbackButton, which is an instance of a Button object. This is needed by the PostBackOptions object to provide context for the JavaScript code. Since we are hiding this button from the programmer, we'll need to find another way to get the event information to him or her. One way to do that is to create our own delegate, and when the PostbackButton delegate is called, call ours. In order to handle this event, write code similar to what you would have for a button click event:

protected void Page_Load(object sender, EventArgs e)
{
    MyPostBackControl.Postback += new EventHandler(MyPostBackControl_PostBack);
}

void MyPostBackControl_PostBack(object sender, EventArgs e)
{
    //Write your code here
}

That's it. As you can see, the source code is available for download at the top of this article. The project itself is in Visual Studio 2008, but you should be able to use the code in a 2005 projects with no trouble. If you have any questions, comments, or improvements, please don't hesitate to contact me.

License

This article, along with any associated source code and files, is licensed under The Common Development and Distribution License (CDDL)

Share

About the Author

Scott Norberg
Technical Lead Adage Technologies
United States United States
Scott started his career in the working world as a band instrument repairman at a music store in the Chicago area. Not long after starting repairing, Scott started teaching himself various web technologies (C++, HTML, CSS, JavaScript, and eventually ASP.NET with C#) and soon discovered that programming matched his interests and abilities much better than repairing band instruments. After working in sales and web development for a music store, he started working for Adage Technologies, a web development consulting firm specializing in custom software solutions. He is currently a lead developer/project manager for a multi-phase, multi-year project for a non-profit firm. He spends most of his free time studying for his MBA at the Kelley School of Business at Indiana University.

Comments and Discussions

 
GeneralMy vote of 5 PinmemberRazi Syed25-May-12 12:17 
GeneralMy vote of 2 PinmemberAcoustic14-Sep-09 18:32 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.150123.1 | Last Updated 8 Sep 2009
Article Copyright 2009 by Scott Norberg
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid