|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
Table of contents
IntroductionThis is the third in a series of articles on a class library for ASP.NET applications that I have developed. It contains a set of common, reusable page classes that can be utilized in web applications as-is to provide a consistent look, feel, and set of features. New classes can also be derived from them to extend their capabilities. The features are all fairly modular and may be extracted and placed into your own classes too. For a complete list of articles in the series along with a demonstration application and the code for the classes, see Part 1 [^]. For the e-mail part of the demo, you will need the SMTP service on the web server or access to a separate SMTP server. The error page demos use an e-mail address stored in the Web.config file that is currently set to a dummy address. You should modify the address specified by the The BasePage class e-mail featuresThis article describes the features of the Two common approachesOne common approach to e-mailing the rendered content of a page is to use the // Create a request for the page that you want
WebRequest wreq = System.Net.HttpWebRequest.Create(
"http://www.mysite.com/mypage.html");
// Get the response
WebResponse wrsp = wreq.GetResponse()
// Get the HTML for the page
StreamReader sr = new StreamReader(wrsp.GetResponseStream())
string strHTML = sr.ReadToEnd()
sr.Close()
// Send it by e-mail
MailMessage msg = new MailMessage();
msg.From = "Somebody@Domain.com"
msg.To = "Anyone@Domain.com"
msg.Subject = "HTML page"
msg.Body = strHTML;
msg.BodyFormat = MailFormat.Html;
SmtpMail.Send(msg);
Another common approach is to override the page's // Create a string builder to contain the HTML
StringBuilder sb = new StringBuilder();
HtmlTextWriter htw =
new HtmlTextWriter(new StringWriter(sb));
// Render the page to it
base.Render(htw);
string strHTML = sb.ToString();
// Send it by e-mail
MailMessage msg = new MailMessage();
msg.From = "Somebody@Domain.com"
msg.To = "Anyone@Domain.com"
msg.Subject = "HTML page"
msg.Body = strHTML;
msg.BodyFormat = MailFormat.Html;
SmtpMail.Send(msg);
// And finally, write the HTML to original writer
writer.Write(strHTML);
While these methods work, they do have some limitations:
The BasePage class benefitsThe
How it worksThe class consists of a property called The EMailRenderedPage propertyThis property is set to The Render methodThe overridden protected override void Render(HtmlTextWriter writer)
{
// If already rendering for e-mail, just render the page
if(!this.IsRenderingForEMail)
{
this.ConvertValMsgsToLinks();
// Rendering normally or going to e-mail?
if(this.EMailRenderedPage)
{
this.RenderForEMail(writer);
return;
}
}
base.Render(writer);
}
The RenderForEMail methodThis method handles all of the details of rendering the page, e-mailing it, and handling any errors that might occur. Note that the code shown below is from the .NET 1.1 version of the class. The .NET 2.0 version is almost identical except for a few minor changes with regard to how the e-mail is sent. In .NET 2.0, it makes use of the new protected void RenderForEMail(HtmlTextWriter writer)
{
StringBuilder sb = new StringBuilder();
HtmlTextWriter hw = new HtmlTextWriter(
new StringWriter(sb, CultureInfo.InvariantCulture));
try
{
isRenderingForEMail = true;
this.Render(hw);
}
finally
{
isRenderingForEMail = false;
}
MailMessage msg = new MailMessage();
// The string builder contains all of the HTML
msg.BodyFormat = MailFormat.Html;
msg.Body = sb.ToString();
EMailPageEventArgs args =
new EMailPageEventArgs(msg, this);
// Get the SMTP server from the Web.config file
// if specified
args.SmtpServer = ConfigurationSettings.AppSettings[
"EMailPage_SmtpServer"];
// Give the derived page a chance to modify or cancel
// the e-mail.
this.OnEMailThisPage(args);
The first thing that occurs is to render the page to a if(args.Cancel == false)
{
// Try sending until it succeeds or told to stop
do
{
try
{
// Turn off retry so we don't get stuck here.
// The error event handler must turn it on if
// a retry is wanted.
args.RetryOnFailure = false;
// It has to come from somebody
if(msg.From == null || msg.From.Length == 0)
throw new ArgumentNullException("From",
"A sender must be specified for " +
"the e-mail message");
// It has to go to somebody
if(msg.To == null || msg.To.Length == 0)
throw new ArgumentNullException("To",
"A recipient must be specified for " +
"the e-mail message");
// Set the server?
if(args.SmtpServer != null &&
args.SmtpServer.Length != 0)
SmtpMail.SmtpServer = args.SmtpServer;
SmtpMail.Send(msg);
}
catch(Exception excp)
{
// Raise an EMailError event if it fails so that
// the derived page can take any action it wants
// including a retry.
EMailErrorEventArgs err = new EMailErrorEventArgs(
args, excp);
this.OnEMailError(err);
}
} while(args.RetryOnFailure == true);
}
// And finally, write the HTML to the original writer.
// It's rendered from the event args in case the handler
// modified it.
writer.Write(args.RenderedContent);
The If e-mail is to be sent, the method checks to see if an SMTP server has been specified in the event arguments by an event handler. If it was, it will use this server name when sending the e-mail. This is useful in situations where your IIS server is not set up to be an SMTP mail server. It also checks to see if sender and recipient e-mail addresses were specified. If not, the e-mail cannot be sent and an exception is thrown stating that fact. If the message is sent successfully, it renders the content to the browser and exits as noted above. If there was an error sending the e-mail, the method raises the E-Mail event handlersThe EMailThisPage eventThis event is raised whenever the page wants to e-mail its content. You should always add a handler for this event so that your page can, at the very least, specify the sender and recipient of the e-mail. Without them, the e-mail cannot be sent. The event passes a custom event arguments class called // This event fires when the page is ready to be e-mailed
void Page_EMailThisPage(Object sender,
EWSoftware.Web.EMailPageEventArgs args)
{
// Set the SMTP server if running locally for testing
if(Page.Request.ServerVariables["HTTP_HOST"] == "localhost")
args.SmtpServer = "REALSMTPSERVER"
// Set sender, recipient, and subject
args.EMail.From = "Somebody@Domain.com"
args.EMail.To = "Anyone@Domain.com"
args.EMail.Subject = this.PageTitle
}
The event argument class' properties and methods are described below.
The constructorsYou will not create an instance of this class yourself. Instead, the page's
The EMailError eventHandling this event is optional. A handler for it can be added if you would like to alter the rendered page, take alternate action if the e-mail fails to get sent, or make changes and attempt to retry sending the e-mail. The event passes a custom event arguments class called The first is The second property in this class is Connecting the event handlersThe .NET 1.1 version contains a delegate for both events. The .NET 2.0 version of the class makes use of the generic event handler type. As such, hooking up the events has a slightly different syntax in the .NET 2.0 version: // .NET 1.1
this.EMailThisPage += new EMailThisPageEventHandler(
this.Page_EMailThisPage);
this.EMailError += new EMailErrorEventHandler(
this.Page_EMailError);
// .NET 2.0
this.EMailThisPage += new EventHandler<EMailPageEventArgs>(
this.Page_EMailThisPage);
this.EMailError += new EventHandler<EMailErrorEventArgs>(
this.Page_EMailError);
ConclusionE-mailing the contents of a rendered page is useful in many situations. The demo application contains some common usage examples such as for the custom error page, user feedback, generating and e-mailing a report, etc. By using this class, you can easily add this ability to any Web Form in your application. Hopefully, you will find this class and the others in the library, or parts of them, as useful as I have. Revision history
|
||||||||||||||||||||||