Friday, September 18, 2009

Be careful using hard coded ValidationGroup in a User Control in ASP.NET

Validation Groups are great in ASP.NET. They allow you to validate a group of controls. You tell ASP.NET what Validation group they are in by specifying a ValidationGroup property on each of the controls that you want in that group.

Simple enough. However, I found out the hard way that if you use the ValidationGroup in a user control you have just made it difficult if not impossible to use your user control more than once on a page.

After I realized that I had the issue, and thought about it for a minute it made sense. Let’s say I have two instances of my user control on my page. There are now twice as many controls in the group than intended. This means unless all the fields in both the user controls pass the validation you will have issues such as submit buttons not submitting (assuming they cause validation to fire).

You can verify this, by looking at the html source for your page. In the JavaScript code, search for “ValidationGroup”. You will see that the validation group is just as you typed it your user control. This means that unlike most other things in ASP.NET, the ValidationGroup is NOT automatically adjusted to take its location in the hierarchy of controls.

What does that mean? That means you have to do this yourself. :) All you have to do is set the ValidationGroup dynamically. The easiest way to do this is to create a property in your code behind.

protected string UniqueValidationGroup { get { return ClientID + "MyValidationGroup"; } }

I chose to use take advantage of the ClientID always having the full path from the page to user control as the ClientID. This means that it is unique from JavaScript. I concatenate that with my ValidationGroup name to give a 100% unique ValidationGroup name. That way, no matter where or how many times your user control is used, the ValidationGroup will be unique.

Now that we have have a unique ValidationGroup name, we need to set it dynamically instead of hardcoding it. You can do this in the code-behind, but I think that can be hard to maintain. I like doing it in the code-behind. Where ever you have ValidationGroup hardcoded, just change it to something like the following (depending on what you called your property in your code-behind).

ValidationGroup='<%# UniqueValidationGroup %>'

Check the JavaScript that is generated from this. You will see that the ValidationGroup is set to a long unique name.

Wednesday, September 16, 2009

Sending Email using C#

While it is not difficult to send email via C#, there tends to be a lot of code that I put in place every time. For starts I like to have a class or at least one method that all email in the application go through. The main reason is so that I can quickly see where the method is called and see where emails are sent. This also aids in debugging, and understanding of code when someone comes onto the project.

One of the first things asked is, how do I turn off emails during development. This provides one location that can be commented out. I take it one step further and make it web.config setting. When email is disabled, I still would like to see a log that it would have been sent. So, I have a log file that the email is written to instead of actually sending the email. The log is only used for development purposes.

I also like to have default email to/from incase the unexpected case of no to/from is encounter when I am not expecting it to. This way I am notified. I also pull the smtp server from the web.config instead of hard coding it. You may also notice I call something I call Config instead of accessing the web.config directly. This is because, I again like to have all access my app settings in one class that can be easily changed if needed. For example, in certain instances configuration may need to be stored in a database instead of the config file. This makes that change very easy to make just by changing and testing one class.

Below is the method / code snippet I use:

public void SendEmail(string fromEmailAddress, string toEmailAddress, string subject, string body, HttpPostedFile attachment)
{
// this should never happen, but just so I will know about it
if (string.IsNullOrEmpty(toEmailAddress))
{
toEmailAddress = "myemail@mydomain.com";
}
// this should never happen, but just so I will know about it
if (string.IsNullOrEmpty(fromEmailAddress))
{
fromEmailAddress = "myemail@mydomain.com";
}

MailMessage msg = new MailMessage(fromEmailAddress, toEmailAddress, subject, body);
Attachment attachmentItem;
if (attachment != null)
{
attachmentItem = new Attachment(attachment.InputStream, attachment.FileName);
msg.Attachments.Add(attachmentItem);
}

msg.IsBodyHtml = false;

SmtpClient smtp = new SmtpClient();
smtp.Host = Config.SmtpServer;

if (Config.AllowEmailsToBeSent)
{
smtp.Send(msg);
}
else
{

StreamWriter writer = new StreamWriter(@"c:\Email.log", true);
using (writer)
{
writer.WriteLine("\r\n\r\nDate/Time Stamp: " + DateTime.Now.ToLocalTime());
writer.WriteLine("From: " + msg.From.Address);
writer.WriteLine("To: " + msg.To[0].Address);
writer.WriteLine("Subject: " + msg.Subject);
writer.WriteLine("Body: " + msg.Body);
if (attachment != null)
{
writer.WriteLine(string.Format("Attachment: {0}", msg.Attachments[0].Name));
}
}
}
}

Tuesday, September 15, 2009

What type of objects are in your Outlook Inbox?

I personally find programming against Outlook from .Net (C# in my case) a bit of trial and error. I recently found out that it is not good to assume that any type of folder only has a particular kind of items in it. In particular, I found out that Undeliverable messages are not of type MailItem, they are of type ReportItem. Go figure! The clue for me was that the icon for these messages in Outlook are different than a normal email message.

Below is a snippet of code that will loop through all the items in your inbox and try to cast it to all the types I could find, and prints out some interesting information about the item. If someone knows of other types, please let me know. If an item is of an unknown type it will write that line with “ERROR: Unknown Item at Index:” message.

There are obviously lots of ways you could write this, but this code was my first thought, and it allows me to actually see the exception if one occurs.

// Create an Outlook Application object. 
Microsoft.Office.Interop.Outlook.Application outLookApp = new Microsoft.Office.Interop.Outlook.Application();

// Print all emails.
NameSpace outlookNS = outLookApp.GetNamespace("MAPI");
MAPIFolder theEmails = outlookNS.GetDefaultFolder(OlDefaultFolders.olFolderInbox);

for (int i = 1; i <= theEmails.Items.Count; i++)
{
object obj = theEmails.Items[i];

// **********************
try
{
AppointmentItem item = (AppointmentItem)obj;
WriteLine(item.Subject);
}
catch (System.Exception ex1)
{
// **********************
try
{
ContactItem item = (ContactItem)obj;
WriteLine(item.FirstName);
}
catch (System.Exception ex2)
{
// **********************
try
{
DistListItem item = (DistListItem)obj;
WriteLine(item.Subject);
}
catch (System.Exception ex3)
{
// **********************
try
{
JournalItem item = (JournalItem)obj;
WriteLine(item.Subject);
}
catch (System.Exception ex4)
{
// **********************
try
{
MailItem item = (MailItem)obj;
WriteLine(item.Subject);
}
catch (System.Exception ex5)
{
// **********************
try
{
NoteItem item = (NoteItem)obj;
WriteLine(item.Subject);
}
catch (System.Exception ex6)
{
// **********************
try
{
PostItem item = (PostItem)obj;
WriteLine(item.Subject);
}
catch (System.Exception ex7)
{
// **********************
try
{
TaskItem item = (TaskItem)obj;
WriteLine(item.Subject);
}
catch (System.Exception ex8)
{
// **********************
try
{
ReportItem item = (ReportItem)obj;
WriteLine(item.Subject);
}
catch (System.Exception ex9)
{
WriteLine(string.Format("ERROR: Unknown Item at Index: {0}", i));
}
}
}
}
}
}
}
}

}

}


A good starting point is: http://msdn.microsoft.com/en-us/library/aa289167(VS.71).aspx#ol03cs_topic11

Also see: http://www.outlook-code.com

Friday, September 4, 2009

Custom Event for your ASP.NET User Control

Custom Event are very useful when you want your ASP.NET User Control to have its own custom events or expose the events of controls within the User Control itself. This allows you to for example create a User Control that has events like MyOkButtonClickEvent and instead of implementing the functionality of that button in your User Control, you can leave it up to the Page or other calling object (such as another User Control) to implement the functionality.

To illustrate my example a little better, let’s assume you have a User Control that you created called UserInputPanel. This control has a textfield and two buttons on it. One button called Cancel and another called OK. We don’t want to implement what happens when either of the buttons is clicked in the User Control itself. Instead, we want the calling object (the Page in this example) to.

There are at least two easy ways to implement this. The difference between the two is that in one case you have a chance to partially implement the functionality in our User Control, in the other, you don’t have that option.

Let’s do the one that give you the least amount of control, but requires the least amount of code.

public partial class UserInputPanel : UserControl
{
public event EventHandler OkButtonClicked;
public event EventHandler CancelButtonClicked;

protected void Page_Load(object sender, Event args e)
{
btnOk.Click += new EventHandler(OkButtonClicked);
btnCancel.Click += new EventHandler(OkButtonClicked);
}
}

In the .aspx page all you have to do is implement the event handlers like you would any other event handlers.

<uc1:UserInputPanel ID="input1" runat="server" OnOkButtonClicked="UserInputOKButton_Click" OnCancelButtonClicked="UserInputCancelButton_Click"/>

In the code-behind (C#) for the Page, you will have two methods that implement the desired functionality.

protected void UserInputOKButton_Click(object sender, EventArgs e)
{
// do stuff here
}

protected void UserInputCancelButton_Click(object sender, EventArgs e)
{
// do stuff here
}


This works great if you want to give the entire implementation details to the calling object, but what if you want to do some validation, provide default behavior, etc how can you do this? Luckily, it is quite easy to extend what we already did. All the code is the same from the calling objects perspective. The only difference is that instead of directly wiring the EventHandlers together, we will create a new one which will give us an opportunity to do what we want to do.

public partial class UserInputPanel : UserControl
{
public event EventHandler OkButtonClicked;
public event EventHandler CancelButtonClicked;

protected void Page_Load(object sender, EventArgs e)
{
btnOk.Click += new EventHandler(btnOk_Click);
btnCancel.Click += new EventHandler(btnCancel_Click);
}

protected void btnCancel_Click(object sender, EventArgs e)
{
// do stuff here

if (CancelButtonClicked != null)
{
CancelButtonClicked(sender, e);
}

// do stuff here
}

protected void btnOk_Click(object sender, EventArgs e)
{
// do stuff here

if (OkButtonClicked != null)
{
OkButtonClicked(sender, e);
}

// do stuff here
}

}

In the above example, we could have use the .aspx page to wire up the click events, but I did it in the Page_Load to be consistent with the other way. The nice thing about this is you can create new events also. You could for example create a new event called OkButtonBeforeClick or OkButtonAfterClick. These are useful when you have partially implemented functionality in the User Control and want to give the calling object more opportunities to fine-tune their functionality.

A side note: Please note that am exposing the EventHandlers as public member variables. This is technically not the Object Oriented way to do it. You should create properties for each event and make the event private instead of what I did, but it just seems so much cleaner this way. Less code :)