jQuery Dialog-Postback but UpdatePanel doesn’t get updated

I assume that it has something to do
with the Dialog not being inside of
the UpdatePanel or something similar.

i’ve also noticed a problem in the
postback-values. All TextBoxes if
empty or not have a comma appended.

You are indeed correct on both counts. The crux of the problem is that the Script Manager “thinks” it is supposed to update an element which jQuery has actually moved to a different location on the page, thus resulting in multiple copies of the element and the problems you have mentioned.

I’ve seen this problem using nested UpdatePanels, but it may occur in other scenarios as well.

This is a problem for which the workarounds are messy.

Option 1 – Change the source code for jQuery UI. I did not have any luck with a quick fix; short of rewriting the entire plugin, I couldn’t find an easy to have the dialog work correctly without reordering the DOM. Also, with that route, now you “own” the source code because you have modified it.

Option 2 – Adjust the DOM whenever the page is rendered partially to remove the duplicate elements. You can output some additional script to cleanup the spurious duplicate element. I don’t like this approach because it allows the DOM to be in an invalid state until the script runs.

Option 3 – Manually override the rendering of the UpdatePanel. Code looks something like this:

private bool _hasDomPresence
{
    get
    {
        return ViewState["__hasDomPresence"] == null ? false : (bool)ViewState["__hasDomPresence"];
    }
    set
    {
        ViewState["__hasDomPresence"] = value;
    }
}

protected override void OnLoad( EventArgs e )
{
    if( !ScriptManager.GetCurrent( this.Page ).IsInAsyncPostBack )
    {
         // a full postback means we no longer have a DOM presence
         _hasDomPresence = false;
    }

    base.OnLoad( e );
}

protected virtual void ShowDetailDialog()
{
    // code to show the offending dialog

    // we are showing it, so note the fact that it now has a DOM presence
    _hasDomPresence = true;
}  

protected override void Render( HtmlTextWriter writer )
{
    foreach( Control c in this.Controls )
    {
        //
        // find the offending control's parent container prior to it being rendered
        // In my scenario, the parent control is just a server-side DIV
        if( c == this.DetailDialog )
        {
            //
            // here, I am checking whether or not the panel actually needs to be
            // rendered. If not, I set it to invisible, thus keeping a new DOM
            // element from being created.
            if( !this.DetailUpdatePanel.IsInPartialRendering && _hasDomPresence )
            {
                this.DetailUpdatePanel.Visible = false;
            }
        }
    }

    base.Render( writer );
}

This also will confuse event validation because the client and server versions of the page don’t match (or at least ASP.Net can’t tell that they do). The only way I could find to make this work was to turn off event validation.

With a proper security model, event validation isn’t 100% necessary but I don’t like being forced to turn it off.

In summary, this is the most evil code I’ve posted on SO and fluffy white kittens will die if you use it, but the approach does seem to work.

Hope this helps.

Leave a Comment