Thursday, May 22, 2008

sending configurable email in Asp.net (Best practice)

Sending email is very common in Asp.net application. In most of asp.net applications I was asked to send email to client or admin etc. Meanwhile, almost always I was asked to change content of email many times. Like change a sentence, put space between sentences. Sometimes to create email the way client needs I had to change email content 10 times. Finally I come up with the idea that I need to make this process configurable and allow clients change the content themselves easily. Another issue is that since email is dependent to other factors like mail server sometimes your application may not be successful to send email so you need detect unsuccessful emails and send email in later steps. This Post will talk about best practice to send email to client. please download the Code

Understanding the issue:

We are going to send email to users. We need these functionalities:

1- The Email content should be configurable

2- We may need to have a link in our email to somewhere in our site or in other sites

3- If sending email is not successful we need to log that email in database to be able to send email in future

You can send email in .net using System.Web.Mail.SmtpMail which is obsolete. Also you can use System.Net.Mail.SmtpClient I highly recommend the second one also try to use System.Net.MailMessage which is new class in .Net 2.0 unless you are using .net 1.1 By using SmtpClint class you can configure your smtp server information in web.config take a look at this code:

Quick look to class diagram:

I need to remind you that I did not use multi tier architecture here. I highly recommend that Accessing to database should be done through DataAccessLayer you can find more information about DataAccessLayer and multi tier programming in my blog.


EmailHelper, EmailLog, EmailLogProvider, DataAccessHelper:


UI will call EmailHelper class methods to send email in our case we have just one type of email if I had 10 different emails (of course with different content) I would have 10 methods to send Emails. All of those 10 methods would use SendEmail method (a private method) to send email. Also in this class there is another method called LogException used to Log the exception in database. Meanwhile, the email information is being saved so we can send email in later step to client. In this method an object of email log is being created then it is passed to EmailLogProvider Insert method to insert into database. DataAccessHelper is a utility class that you may use to add parameter to a command and to run a storedprocedures. In our example it is being used by EmailLogProvider class.

EmailReader, EmailLinkLoader:

When a method of EmailHelper is being called to send an email first a MailMessage object is created afterwards, it is passed to EmailReader class to prepare the body and other information. In this method we load information form an Xml file. So it is highly maintainable because as long as client gets back to us to change content of email we can apply those changes in this xml file not to our code. Take a look of this xml file.



As you see we even have "from emai"l and "from email display name" also as many as required bcc email can be configured. A very nice trick in this code is that if you look closer to the xml file you will find $firstName$ . This is a key for our code and we will replace this value in EmailLoader.LoadRegistration .So the email can have dynamic information for example another good example is that you may want to send username and password to a user but this information may vary from one user to another user so we use other keys and we replace this information in our code exactly the same way for $firstName$. In most of the sites that I worked I had more than one email also many of them had some special links like Terms and Condition link that should be placed into email. A good practice always suggests that never put a link hard coded as long as you have more than one email content connecting to the same link. So imagine you have 5 email and all of them somewhere in their content have a link to Terms and condition. You better make this link configurable because when this link changes you need change just one configuration rather than looking for this link in all emails. So EmailLinkLoader actually load another xml file and find the link address then cache this information. So next time it does not need to look up link again. This link information is passed to EmailReader to be applied to body content.




Important (how to run the code)


Open Visual studio and form file menu select open web site and form file system select the project folder. Afterwards you can run the project. You need to apply smtpserver address. A good test is without applying smtpserver if you run application then application ask your first Name and your email address. Afterwards since sending email is not successful the email information is saved into database. And it shows you unsuccessful message. In later steps we can use EmailLogProvider class and load all EmailLog objects so we can retry and resend email.


please download the Code

Tuesday, May 20, 2008

Multi Tier Sample Code (Best Practice)

see these Related topics:

  1. Multi tier basics
  2. A best practice for multi tier architecture
  3. A sample code based on best practice
  4. Examine utilities to speed up Multi tier programming- NLog
In previous lessons I discussed about different layers and now I am going to Show you a sample code and discus what goes where.


We are going to create a web application to show different products and add products. See the database definition:


First open visual studio then create an empty solution afterwards add these projects to the Solution:

Common Layer (A class library)
In this layer we are going to define business entities and interfaces. Also sometimes we may define enumerations since it should be understandable for all other layers. We may want log information so having a logger class here could be useful serving all layers. The best tool for logging information and bugs is NLog (I will explain how to work with NLog in future posts). We also need a serviceFacotry class to create proper object of Facade layer. If you look at the architecture (previous lesson) you will see that UIProvider layer connect to facade layer but we may need to change this facade layer to a webservice so creating object from this layer should be configurable. One way is that a service factory can be used another way is using Spring. I will talk about Spring in future posts. Please look at the sample code.


Let's look at the code in ServiceFactory class:

using System;

using System.Collections.Generic;

using System.Text;

using MultiTier.Common.ServiceInterface;

using MultiTier.Common.BusinessEntities;

using System.Configuration;

using System.Reflection;

using System.Web;

namespace MultiTier.Common

{

public class ServiceFactory

{

private static Assembly asm;

public static IProductService GetProductService()

{

if (asm == null)

{

//Load Assembly

string AssemblyName = ConfigurationManager.AppSettings["Assembly"];

string asmPath = HttpContext.Current.Server.MapPath("~/bin/" + AssemblyName);

asm = Assembly.LoadFile(asmPath);

if (asm == null)

throw new Exception("Assembly could not be found: " + AssemblyName);

}

string className = ConfigurationManager.AppSettings["Product"];

IProductService obj = asm.CreateInstance(className) as IProductService;

if (obj == null)

throw new Exception("class could not be created: " + className);

return obj;

}

}

}

There are different ways of implementing ServiceFactory. This implementation is the simplest way but not the efficient way. I would say using spring is the best approach. Firstly a proper assembly is loaded then a new product object is created afterwards it is casted to the IProductService interface finally object is returned as IProductService. What you need to know is that we are using Reflection to load assembly and to create productService object. The address of assembly and the class name that we need to create object is configured in configuration file (in our case this configuration is web.config in UI project)

Data Access Layer (a class library)

The main purpose of this layer is to save and retrieve data from database. So there is a class named "ProductDal" gets data from database and map the data to the business entity. And send it back to BL layer. In ProductDal some stored procedures are called and a helper class is created to add parameter for each stored procedure. (Please download the source code)

Business Layer (a class library)

In This business layer we do not have any special business but let me give you an example if a user select bunch of products to buy then in this layer the price should be calculated. And then some code will be written here to withdraw his account.

Facade Layer (a class library)

The responsibility of this layer is that make it easier for UI to connect to this layer without understanding the complexity of backend. Let me give you an example. In this layer we may add some code to log accessing to data also we may check security etc. Please see the code.

UIProvider Layer (a class library)
What you need in UI may different in terms of object entities so you need add some modification or even create new objects to bind to UI elements. Moreover, you can test this layer so you know what is binding to UI. Best practice suggests that we should test this layer to sure about data which is going to be bind to UI. One of the best tools for testing is NUnit that I am going to talk about NUnit in next lessons.

UI(a web application)
Main purpose of this layer is showing information to user and getting information from user. In our case this layer is a web application. As you see I applied a css (some free template form dear Google search). There is a Master page and also two pages, one page to add Product and another to see list of products. In both pages I used object data bindings. Please get the code.
In next Lesson I am going to talk about NLog, Spring, NUnit and my favourite tool "code smith" to generate code automatically. I am sure you came up with the idea that this is really time consuming and you need something to speed up your implementation. Code smith helps you to generate code automatically and fast.

Important: After getting the code you need to change the connection string (It depends on where you put the sample code but if you look at the sample code there is a database that is in web.config you need to specify address of this file)