views:

65

answers:

3

I am maintaining an ASP.NET site, and I was attempting to get the dialogs looking better using jQuery. The web application has a C# class called MessageBox which allows messages to be shown to the client from the server side.... essentially in the C# on an aspx codebehind if some logic 'does not compute', you can just MessageBox.Show('your error message');

Since the MessageBox class appeared to just 'inject' javascript...the "alert(your message)" I tried changing the javascript to a jquery dialog call:

html: the standard jQuery example dialog... (cut off the tags on purpose...just to get the code example to show up... there is probably a real way to do this on here... but this is my first post...)

div id="dialog" title="Example dialog">
 p>Some text that you want to display to the user./p>
/div>

jQuery: I commented out the Alert, and substituted: sb.Append("$('dialog').dialog('open');");

while( iMsgCount-- > 0 )
{
  sMsg = (string) queue.Dequeue();
  sMsg = sMsg.Replace( "\n", "\\n" );
  sMsg = sMsg.Replace( "\"", "'" );
  //sb.Append( @"alert( """ + sMsg + @""" );" );

  **** sb.Append("$('dialog').dialog('open');"); ****
}

I was expecting this to open the dialog set up in html, however nothing shows. I figured javascript is javascript... and that executing instead a jQuery call versus manual Alert wouldn't matter... however clearly there is a disconnect.

Any thoughts on how to solve this problem? Or any better implementations out there I am not aware of?

Thanks, for any and all help... I've include the full MessageBox class below.

Curt.

public class MessageBox
{
    private static Hashtable m_executingPages = new Hashtable();

 private MessageBox(){}

    public static void Show( string sMessage )
    {
       if( !m_executingPages.Contains( HttpContext.Current.Handler ) )
       {
          Page executingPage = HttpContext.Current.Handler as Page;
          if( executingPage != null )
          {
             Queue messageQueue = new Queue();
             messageQueue.Enqueue( sMessage );
             m_executingPages.Add( HttpContext.Current.Handler, messageQueue );
             executingPage.Unload += new EventHandler( ExecutingPage_Unload );
          }   
       }
       else
       {
          Queue queue = (Queue) m_executingPages[ HttpContext.Current.Handler ];
          queue.Enqueue( sMessage );
       }
    }

    private static void ExecutingPage_Unload(object sender, EventArgs e)
    {
       Queue queue = (Queue) m_executingPages[ HttpContext.Current.Handler ];
       if( queue != null )
       {
          StringBuilder sb = new StringBuilder();
          int iMsgCount = queue.Count;
          sb.Append( "" );
          string sMsg;
          while( iMsgCount-- > 0 )
          {
             sMsg = (string) queue.Dequeue();
             sMsg = sMsg.Replace( "\n", "\\n" );
             sMsg = sMsg.Replace( "\"", "'" );
             sb.Append( @"alert( """ + sMsg + @""" );" );
          }

          sb.Append( @"" );
          m_executingPages.Remove( HttpContext.Current.Handler );
          HttpContext.Current.Response.Write( sb.ToString() );
       }
    }
 }
A: 

Wrap the emitted Javascript in $(function() { ... }).

SLaks
Thanks for the suggestion...I gave this a shot, unfortunately, it did not seem to work, any other ideas?
Curt
Do you get any script errors?
SLaks
A: 

"The Unload() event is raised after the page has been fully rendered, sent to the client, and is ready to be discarded. At this point, page properties such as Response() and Request() are unloaded and cleanup is performed." http://msdn.microsoft.com/en-us/library/ms178472.aspx

You have to add your output during the Rendering of the page and not in the Unload event.

After reading above that it works with "alert" I'm going to say my answer isn't going to help. However I will say that is strange that it does work since it shouldn't given the way events are fired in asp.net

BuildStarted
+1  A: 

this is bizarre... I wrote a class almost identical a long time ago. for a second I thought you were using it!

anyway, I dug up the code from mine. I've used it quite a bit. It allows you to specify a "Callback" function name in case you want to not use the "alert" functionality.

btw, you need to be careful with the static Hashtable. if you have multiple people using the app at the same time, they might get each other's messages.

usage:

<webapp:MessageBox ID="messageBox" Callback="showMessage" runat="server" />
<script type="text/javascript">
    function showMessage(messages) {
        $("#dialog p").empty();
        for(var msg in messages) {
            $("#dialog p").html += msg;
        }
        $("#dialog p").show();
    }
</script>

I didn't test the callback script, but you get the idea.

and the code:

/// <summary>
/// MessageBox is a class that allows a developer to enqueue messages to be
/// displayed to the user on the client side, when the page next loads
/// </summary>
public class MessageBox : System.Web.UI.UserControl
{

    /// <summary>
    /// queues up a message to be displayed on the next rendering.
    /// </summary>
    public static void Show( string message )
    {
        Messages.Enqueue( message );
    }

    /// <summary>
    /// queues up a message to be displayed on the next rendering.
    /// </summary>
    public static void Show( string message, params object[] args )
    {
        Show( string.Format( message, args ) );
    }

    /// <summary>
    /// override of OnPreRender to render any items in the queue as javascript
    /// </summary>
    protected override void OnPreRender( EventArgs e )
    {
        base.OnPreRender( e );

        if ( Messages.Count > 0 )
        {

            StringBuilder script = new StringBuilder();
            int count = 0;

            script.AppendLine( "var messages = new Array();" );

            while ( Messages.Count > 0 )
            {
                string text = Messages.Dequeue();
                text = text.Replace( "\\", "\\\\" );
                text = text.Replace( "\'", "\\\'" );
                text = text.Replace( "\r", "\\r" );
                text = text.Replace( "\n", "\\n" );

                script.AppendFormat( "messages[{0}] = '{1}';{2}", count++, HttpUtility.HtmlEncode(text), Environment.NewLine );
            }

            if ( string.IsNullOrEmpty( Callback ) )
            {
                // display as "alert"s if callback is not specified
                script.AppendFormat( "for(i=0;i<messages.length;i++) alert(messages[i]);{0}", Environment.NewLine );
            }
            else
            {
                // call the callback if specified
                script.AppendFormat( "{0}(messages);{1}", Callback, Environment.NewLine );
            }

            Page.ClientScript.RegisterStartupScript( this.GetType(), "messages", script.ToString(), true );
        }
    }

    /// <summary>
    /// gets or sets the name of the javascript method to call to display the messages
    /// </summary>
    public string Callback
    {
        get { return callback; }
        set { callback = value; }
    }
    private string callback;

    /// <summary>
    /// helper to expose the queue in the session
    /// </summary>
    private static Queue<string> Messages
    {
        get
        {
            Queue<string> messages = (Queue<string>)HttpContext.Current.Session[MessageQueue];
            if ( messages == null )
            {
                messages = new Queue<string>();
                HttpContext.Current.Session[MessageQueue] = messages;
            }
            return messages;
        }
    }
    private static string MessageQueue = "MessageQueue";

}
dave thieben
This seemed to work. I had to tweak my code a bit, and figure out how to rewire the ok / confirm buttons, but server side Alerts / Confirms seem to be working... will have to bang on it some more. But thank you for getting me almost all the way there. :)
Curt