Web Messaging using Eeeksoft's Popup window control

Every web project requires some standard way of returning typical information and error reporting feedback to the user.

A common method is to reserve some portion of the screen, near the top under an application banner, near the submit controls or some other arbitrary combination. To preserve on screen real estate, some developers create collapsable sections or popup windows. I have been using Eeeksoft's popup window control as an easy way of displaying information for some time now. Eeeksoft's popup window control provides an Exchange-like feel for messaging and preserves valuable on screen real estate. And the best part is it's free!

You can read Thomas Petricek's original article here or check out Eeeksoft's website here.

I’ve created a simple routine which takes in a pages particular popup window and displays information messages using a blue color scheme which will dissapear after 5 seconds and displays error messages using a red color scheme with no timeout.

Now on to the implementation...

 

Once you've added a reference to the control…

EeekSoft.Web.PopupWin.dll
 
 
.. you can drag and drop a popup window onto your web page from the toolbar. It doesn’t really matter where you place it since it’s going to be invisible anyway. When it appears, by default it will show up as a popup window in the lower right hand side of the screen. Drag/Dropping the control onto the page renders the prefix code…
 
<!-- Popup.aspx -->
<%@ Register TagPrefix="cc1" Namespace="EeekSoft.Web" Assembly="EeekSoft.Web.PopupWin" %>
 
…and adds the following instance…
 
<cc1:popupwin id="popupWin" runat="server" visible="False" 
  colorstyle="Blue" width="230px" height="100px" dockmode="BottomLeft" 
  windowscroll="False" windowsize="300, 200" />

…finally, add this code to a utility class for your web project (e.g. WebUtility class in the AppCode folder):

public static void ShowMessages(EeekSoft.Web.PopupWin PopupWin1, Page P)

    {

        //Display Error Message

        if ((P.Session["InfoMessage"] == null) && (P.Session["ErrorMessage"] == null))

        {

            PopupWin1.Visible = false;

        }

 

        if (P.Session["ErrorMessage"] != null)

        {

            PopupWin1.Message = P.Session["ErrorMessage"].ToString();

            PopupWin1.Title = "Error Window";

            PopupWin1.Text = P.Session["ErrorMessage"].ToString();

            PopupWin1.ColorStyle = EeekSoft.Web.PopupColorStyle.Red;

            PopupWin1.Visible = true;

            PopupWin1.HideAfter = -1;

            PopupWin1.PopupSpeed = 1;

            P.Session["ErrorMessage"] = null; //clear message after read

        }

        else //display info message if there was no error

        {

            //Display Info Message if there is one

            if (P.Session["InfoMessage"] != null)

            {

                PopupWin1.Message = P.Session["InfoMessage"].ToString();

                PopupWin1.Title = "Information Window";

                PopupWin1.Text = P.Session["InfoMessage"].ToString();

                PopupWin1.ColorStyle = EeekSoft.Web.PopupColorStyle.Blue;

                PopupWin1.Visible = true;

                PopupWin1.HideAfter = 5000;

                P.Session["InfoMessage"] = null; //clear message after read

            }

        }

    } //ShowMessages

 

You can now happily code your messages using this simple procedure. Set information messages into the session variable “InfoMessage”, and set error messages into the session variable “ErrorMessage”. Call “ShowMessages” to display the popup window with your message on the screen. Include the call to ShowMessages in Page.Load on every page to report basic information and error messages when errors occur from other pages redirecting to your target page. Here are some examples:

 

Example 1. Let’s say you have a list product page which displays a list of all projects. The user attempts to edit one but the edit page returns to the list page when the product is not found. This happens when another user deletes the product for example. All you need to do to get the message from the edit page to display on the list page is include the showmessages call on page load.

ShowMessages(EeekSoft.Web.PopupWin PopupWin1, Page P)

To store the message for later retrieval from the edit page add:

Session[“ErrorMessage”] = “Unable to edit product!”;

Example 2. Let’s say you want to show either a success message or an error message when saving changes to a product. You add code like the following:

protected SaveProduct()

{

      string errmsg = "";

      string infomsg = "";

     

      try

      {

            Product.Save();

            infomsg = "Product Saved!";

      }

      catch (Exception ex)

{

errmsg = "Error trying to save product: " + ex.Message;

}

 

      if (errmsg.Length > 0)

      {

            Session["ErrorMessage"] = errmsg;

            WebUtility.ShowMessages(PopupWin1, Page);

      }

 

      if (infomsg.Length > 0)

      {

            Session["InfoMessage"] = infomsg;

            response.redirect("ProductList.aspx", true);

      }

}

 

 

 

 

EnableEventValidation error on button postback using a multipart form in .NET v2.0

I had a problem today using a multipart form which gave me the following error:

 

“Invalid postback or callback argument. 

Event validation is enabled using <pages enableEventValidation="true"/> in configuration or

<%@ Page EnableEventValidation="true" %> in a page. 

 

For security purposes, this feature verifies that arguments to postback or callback events

originate from the server control that originally rendered them.  If the data is valid

and expected, use the ClientScriptManager.RegisterForEventValidation method in order to

register the postback or callback data for validation.”

 

The code I’m using worked with .net Beta 2 but broke after upgrading. I tried adding the

 

<%@ Page EnableEventValidation="true" %>

 

setting, tried overriding Page.Render and adding the

 

ClientScriptManager.RegisterForEventValidation(btnSubmit.UniqueID)

 

 all to no avail. I finally got it working by setting validation to false e.g.:

 

<%@ Page EnableEventValidation="false" %>

 

I didn’t find much documentation googling this error so, hope it helps.

 

 

GridView In-Place Editing Revisited

 

For my first post, I’m going to revisit an article by AzamSharp which shows a simple approach to building GridViews with add/edit/update/delete functionality and offer some suggested improvements to make it even simpler!

 

Read the original article here:

 

http://geekswithblogs.net/AzamSharp/archive/2006/01/12/65647.aspx

 

 

The original interface supports adding rows through a set of controls in the footer of the GridView. Here is the original interface.

 

Original GridView

 

While this is an excellent example of how to add controls to the footer, this interface places the add controls at the bottom of the grid. For a table with only a few rows this isn’t a problem but if there are many rows then the add row is at the bottom of the page which is an awkward position. Even worse, the user may be forced to scroll, hiding the add functionality altogether. Also, adding controls to the footer forces the coder to create ItemTemplate column definitions instead of using simpler Bound columns.

 

I would suggest moving this functionality out of the GridView to the top of the page. Here is the new look.

 

New GridView with Add functionality at top of page

 

 

To move the Add functionality out of the GridView, I’ll add a table with some textboxes and an Add button. I’ll create an event handler for the add button’s click event which will add the new user. Now that the add functionality has been moved out of the GridView, the ItemTemplates can be replaced with Bound columns and we can remove the event handlers for OnRowCancelingEdit, OnRowEditing, OnRowUpdating, OnRowUpdated, OnRowDeleting and OnRowCommand. We can remove all of the code-behind event handling too since it’s no longer needed. We need to make the ID column readonly so the end user can’t change it and I’ll add the GridView tag for EmptyDataText=”No Users Found!”, just in case there are no users. Finally, I’ll add a namespace for the App_Code User class called myApp so User is the App_Code User and not System.Security.Principal.IPrincipal.Page.User. This also requires prefixing the TypeName attribute for the GridView with the new namespace. Here is the new Default.aspx page.

 

<%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" %>

 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

 

<html xmlns="http://www.w3.org/1999/xhtml" >

<head runat="server">

    <title>Untitled Page</title>

</head>

<body>

    <form id="form1" runat="server">

   

    <table>

        <tr>

            <td>First Name:</td>

            <td><asp:TextBox ID="txtAddFirstName" runat="server"></asp:TextBox></td>

        </tr>

        <tr>

            <td>Last Name:</td>

            <td><asp:TextBox ID="txtAddLastName" runat="server"></asp:TextBox></td>

        </tr>

        <tr>

            <td><asp:Button ID="Btn_Add" runat="server" Text="Add" OnClick="Btn_Add_Click" />

</td>

            <td></td>

        </tr>

    </table>

   

    <div>

        <asp:GridView DataSourceID="objUser" ID="GridView1" runat="server" AutoGenerateColumns="False"

            DataKeyNames="ID"

            EmptyDataText="No Users Found!">

            <Columns>

                <asp:BoundField HeaderText="UserID" DataField="ID" ReadOnly="true" />

                <asp:BoundField HeaderText="First Name" DataField="FirstName" />

                <asp:BoundField HeaderText="Last Name" DataField="LastName" />

                <asp:CommandField HeaderText="Edit" ShowEditButton="True" />

                <asp:CommandField HeaderText="Delete" ShowDeleteButton="True" />

            </Columns>

        </asp:GridView>

       

        <asp:ObjectDataSource ID="objUser" runat="server"

            DeleteMethod="DeleteUser"

            InsertMethod="AddUser"  

            SelectMethod="GetAllUsers"

            UpdateMethod="UpdateUser"

            TypeName="myApp.User">

        </asp:ObjectDataSource>

   

    </div>

    </form>

</body>

</html>

 

 

 

And here is the new Default.aspx.cs code-behind page:

 

using System;

using System.Data;

using System.Configuration;

using System.Web;

using System.Web.Security;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

using System.Web.UI.HtmlControls;

using System.Collections;

 

public partial class _Default : System.Web.UI.Page

{

    protected void Page_Load(object sender, EventArgs e)

    {

    }

 

    protected void Btn_Add_Click(object sender, EventArgs e)

    {

        myApp.User U = new myApp.User();

        U.AddUser(txtAddFirstName.Text, txtAddLastName.Text);

        this.GridView1.DataBind();

    }

}

 

 

And here’s the new User.cs class:

 

using System;

using System.Data;

using System.Configuration;

using System.Web;

using System.Web.Security;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

using System.Web.UI.HtmlControls;

using System.Collections.Generic;

using System.Data.SqlClient;

 

namespace myApp

{

    public class User

    {

 

        .../* Remaining Code Unchanged */...

 

}//namespace myApp

 

 

 

Now that’s a simple page! I would suggest refactoring the User class with a static Add method but other than that it’s pretty clean. Anyway, I hope you like my first post. Comments and suggestions welcome!