ASP.NET developers are always looking for ways to improve their user interfaces. In the past few years, numerous AJAX frameworks have emerged, allowing developers to create applications that look and feel like software you might find on the desktop. Microsoft has released its own Ajax framework for ASP.NET to make this task easier for developers. Many developers, however, are not in a position to introduce a new framework to existing applications. Instead, they might prefer to add their own code to improve one aspect of the interface as a particular need arises. This article demonstrates how developers can introduce one of the more popular features of desktop applications to their ASP.NET solutions: modal windows that convey user feedback. Providing feedback in this manner is very effective because modal windows effectively disable the rest of the application, thereby forcing the user to acknowledge the message. Modal windows are common throughout thick-client applications but they are challenging to implement in browser-based solutions. The approach described in this article will allow developers to implement this feature, without installing any new framework, and with only a small amount of code and markup.
The demonstration provided here assumes developers are using the 2.0 version of the .NET framework of higher because it utilizes an ASP.NET Master Page. However, applications based upon the 1.1 framework could still implement a similar approach, by placing the logic elsewhere, such as a UserControl.
The basic concept is this: Users interact with your application, retrieving data and modifying that data, and then the application provides feedback based upon their actions. ASP.NET has always provided numerous validation controls that are capable of displaying error messages on a web form. The downside to this approach is that the user might miss this information, even when the error message is presented in a different color. To remedy this, some developers prefer to use JavaScript alert windows. These alert windows can be useful, especially when they are made ‘modal’. Having said that, support for modal alerts in JavaScript is problematic because of lack of consistency across browsers.
The solution presented here is a simple one. It consists of a Message class, a MessageProvider class to work with Message instances, and a Default.master (your Master Page) containing the code necessary to display messages to the user. Finally, the user will create their ASP.NET pages that will extend the Master Page to make use of the framework. The class that represents a system message, which you will appropriately call Message, has two properties: Text and Type. Text will contain the message that eventually will display to the user. Type is a property of type int that will contain one of the following values defined in the enum MsgType defined in the same class:
public enum MsgType { INFORMATIONAL, WARNING, ERROR }
The MessageProvider class is a Singleton that the application uses to manage Message instances. There is really not much to it in its present form. It contains a public property, called Messages, that will return a strongly typed collection of Message instances:
private IList<Message> msgs = new List<Message>(); public IList<Message> Messages { get { return msgs; } }
As mentioned previously, you utilize a ASP.NET 2.0 Master Page to display these messages. If you are unable to use a MasterPage, you could add this code in a UserControl. The key is that you will want to put the code somewhere that all of your pages can reuse. In the markup of the Default.master file, you declare an asp:Panel called “MessageContainer” that contains markup within a <div> tags. This panel’s visibility will be toggled on when messages are ready to display. A <span> tag will be populated with message text and one of three different icons that accompany each of the three different message types. A single button is provided for the user to acknowledge the alert. There is some additional javaScript code needed, some of which is used to hide any dropdown lists that might be on the page (this is due to an Internet Explorer limitation that allows dropdowns to display through <div> tags even though they have a higher z-index.). The Default.master.cs file will implement a PreRender method that checks for messages and generates the markup to display them:
protected void Page_PreRender(object sender, EventArgs e) { StringBuilder sb = new StringBuilder(); string imgStr = null; sb.Append("<div style="width:530px;padding-left:10px; padding-right:10px;">"); if (MessageProvider.getInstance().Messages.Count > 0) { MessageContainer.Visible = true; } else { MessageContainer.Visible = false; } foreach (Message msg in MessageProvider.getInstance().Messages) { switch (msg.Type) { case (int)Message.MsgType.INFORMATIONAL: imgStr = "info.ico"; break; case (int)Message.MsgType.WARNING: imgStr = "warning.ico"; break; case (int)Message.MsgType.ERROR: imgStr = "error.ico"; break; } sb.Append("<div style="valign=middle;float:left; "<img src="" + imgStr + ""<>/div<"); sb.Append("<div style="valign:middle;text-align:left; "<" + msg.Text + ">/div<>br/<"); } sb.Append("</div>"); MessageProvider.getInstance().Messages.Clear(); this.spanMsg.InnerHtml = sb.ToString(); }
That’s it. The messaging framework is now in place. I have created a simple FormView in Default.aspx that collects first and last name for an individual and attempts to save the record to the database. However, before any data saves can occur, you need to perform some validation. You will add any errors to your collection and let the Master Page display them. Because you’ve really created an ‘informational’ framework that is capable of displaying more than just errors, you can provide users with warning and informational messages as well. The following event handler in Default.aspx.cs fires when the ‘Save’ button is pressed. You check user input, potentially saving that record to the database, and add it to your Message collection as necessary:
protected void btnSave_OnClick(object sender, EventArgs e) { string firstName = ((TextBox)this.fvEmployeeData.FindControl ("txtFirstName")).Text; string lastName = ((TextBox)this.fvEmployeeData.FindControl ("txtlastName")).Text; MessageProvider msgProvider = MessageProvider.getInstance(); bool hasErrors = false; if (lastName == null || lastName.Trim().Equals("")) { msgProvider.Messages.Add(new Message("You must enter a last name.", Message.MsgType.ERROR)); hasErrors = true; } //If okay, submit... if (!hasErrors) { if (firstName == null || firstName.Trim().Equals("")) { msgProvider.Messages.Add( new Message("No first name was entered. Please update as soon as possible.", Message.MsgType.WARNING)); } try { this.fvEmployeeData.InsertItem(false); msgProvider.Messages.Add(new Message("Record saved.", Message.MsgType.INFORMATIONAL)); } catch (Exception ex) { msgProvider.Messages.Add(new Message("Unexpected error occurred: " + ex.Message, Message.MsgType.ERROR)); } } }
In the preceeding code, you consider a last name to be required data. If it is not provided, an error message is created. If a first name is not entered, you allow the save to proceed but warn the user to enter one at a future date. Upon a successful save, you provided user feedback as well. There is no limit on the number of messages that can be displayed and different types of messages may be displayed simultaneously. The contents of the IList<Message> are displayed after each postback and then the messages are removed.
Error when user fails to enter last name
‘Warning’ message along with an ‘Informational’ message when a user saves without first name
Message upon successful save
Conclusion
With this system in place, you can enhance your ASP.NET applications with modal windows that provider user feedback in a clean and efficient manner.
About the Author
Michael Klaene is a Senior Consultant with Sogeti LLC. He has spent over nine years in IT, specializing in J2EE, .NET, and Oracle analysis and development.