How can I handle all my errors / messages in one place on an Asp.Net page?
I'm looking for some advice here.
On my site, I put things in web user controls. For example, I will have a NewsItem control, an article control, a ContactForm control.
They will appear in various places on my site.
What I am looking for is a way for these controls to pass messages to the page they exist on.
I don't want to tie them tightly, so I think I'll have to do it with events / delegates. I am a bit confused about how to implement this.
A few examples:
1
Contact form submitted. Once it's posted, instead of replacing myself with "your email sent", which restricts the posting of this post, I would just like to notify the page that the control is enabled with a "Status" message and possibly suggested behavior. So the message will include text to render as well enum
as how DisplayAs.Popup
orDisplayAs.Success
2
Article control queries the database for the Article object. The database returns an exception. The custom exception is passed to the page along with the enumeration DisplayAs.Error
. The page handles this error and displays it wherever errors occur.
I am trying to do something similar to the ValidationSummary control, except that I want the page to display messages when the enumeration deems appropriate.
Again, I don't want to tightly tie or rely on the control that exists on the page. I want the controls to raise these events, but the page can ignore them if it wants to.
Am I going to do it right?
I would like a sample code
to get me started.
I know this is a more difficult question, so I will wait before voting and choosing the answers.
a source to share
You might be bubbling when an event happens from a child to a parent page. The parent page can register this event and use it (if useful).
Parent ASPX
<uc1:ChildControl runat="server" ID="cc1" OnSomeEvent="cc1_SomeEvent" />
Parent C #
protected void cc1_SomeEvent(object sender, EventArgs e)
{
// Handler event
}
Child C #
public event EventHandler OnSomeEvent;
protected void ErrorOccurInControl()
{
if (this.OnSomeEvent != null)
{
this.OnSomeEvent(this, new EventArgs());
}
}
protected override void OnLoad(EventArgs e)
{
ErrorOccurInControl();
}
a source to share
The following assumes that you know that all controls are on a page like App.YourPage
Here is a quick message box that I put on a MasterPage or page and just call from any page or control. (Excuse it in VB.net, not C #)
You can extend your AddMessage application to login and perform another transactional action (I pulled our controller logic out of it)
from any control:
CType(Page, App.YourPage).messageBox.AddMessage(
ctrlMessageBox.MessageTypes.InfoMessage
,"Updated Successfully")
Control:
Public Class ctrlMessageBox
Inherits System.Web.UI.UserControl
'List of types that a message could be
Enum MessageTypes
InfoMessage
ErrorMessage
WarningMessage
End Enum
#Region "[Message] inner class for structered message object"
Public Class Message
Private _messageText As String
Private _messageType As MessageTypes
Public Property MessageText() As String
Get
Return _messageText
End Get
Set(ByVal value As String)
_messageText = value
End Set
End Property
Public Property MessageType() As MessageTypes
Get
Return _messageType
End Get
Set(ByVal value As MessageTypes)
_messageType = value
End Set
End Property
End Class
#End Region
'storage of all message objects
Private _messages As New List(Of Message)
'Creates a Message object and adds it to the collection
Public Sub addMessage(ByVal MessageType As MessageTypes, ByVal MessageText As String)
Page.Trace.Warn(Me.GetType.Name, String.Format("addMessage({0},{1})", MessageType.ToString, MessageText))
Dim msg As New Message
msg.MessageText = MessageText
msg.MessageType = MessageType
_messages.Add(msg)
End Sub
Protected Sub Page_PreRender(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.PreRender
' Page.Trace.Warn(Me.GetType.Name, String.Format("Page_PreRender(_messages.Count={0})", _messages.Count))
End Sub
Public Overrides Sub RenderControl(ByVal writer As System.Web.UI.HtmlTextWriter)
Page.Trace.Warn(Me.GetType.Name, String.Format("ctrlMessageBox.RenderControl(_messages.Count={0})", _messages.Count))
'draws the message box on the page with all messages
If _messages.Count = 0 Then Return
Dim sbHTML As New StringBuilder
sbHTML.Append("<div id='MessageBox'>")
For Each msg As Message In _messages
sbHTML.AppendFormat("<p><img src='{0}'> {1}</p>", getImage(msg.MessageType), msg.MessageText)
Next
sbHTML.Append("</div>")
writer.Write(sbHTML.ToString)
'dim ctrlLiteral As New Literal()
'ctrlLiteral.Text = sbHTML.ToString
'Me.Controls.Add(ctrlLiteral)
End Sub
'returns a specific image based on the message type
Protected Function getImage(ByVal type As MessageTypes) As String
Select Case type
Case MessageTypes.ErrorMessage
Return Page.ResolveUrl("~/images/icons/error.gif")
Case MessageTypes.InfoMessage
Return Page.ResolveUrl("~/images/icons/icon-status-info.gif")
Case MessageTypes.WarningMessage
Return Page.ResolveUrl("~/images/icons/icon-exclaim.gif")
Case Else
Return ""
End Select
End Function
End Class
a source to share
Data annotation validators are really good for this type of thing. They are commonly used in ASP.NET MVC, but they work great in WebForms. You can use the built-in validators or create your own that do more complex validation.
This example is in VB.NET, but it shouldn't be hard for you to see this value:
http://adventuresdotnet.blogspot.com/2009/08/aspnet-webforms-validation-with-data.html
a source to share