asp tutorials, asp.net tutorials, sample code, and Microsoft news from 15Seconds
Data Access  |   Troubleshooting  |   Security  |   Performance  |   ADSI  |   Upload  |   Email  |   Control Building  |   Component Building  |   Forms  |   XML  |   Web Services  |   ASP.NET  |   .NET Features  |   .NET 2.0  |   App Development  |   App Architecture  |   IIS  |   Wireless
 
Pioneering Active Server
 Power Search





Active News
15 Seconds Weekly Newsletter
• Complete Coverage
• Site Updates
• Upcoming Features

More Free Newsletters
Reference
News
Articles
Archive
Writers
Code Samples
Components
Tools
FAQ
Feedback
Books
Links
DL Archives
Community
Messageboard
List Servers
Mailing List
WebHosts
Consultants
Tech Jobs
15 Seconds
Home
Site Map
Press
Legal
Privacy Policy
internet.commerce














internet.com
IT
Developer
Internet News
Small Business
Personal Technology
International

Search internet.com
Advertise
Corporate Info
Newsletters
Tech Jobs
E-mail Offers

HardwareCentral
Compare products, prices, and stores at Hardware Central!

In-Memory E-mail Attachments in ASP.NET 2.0
By Wayne Berry
Rating: 3.1 out of 5
Rate this article


  • email this article to a colleague
  • suggest an article


    In previous versions of classic ASP and ASP.NET 1.x, there has always been a requirement that an attachment exist on the hard disk before it can be attached to an outbound email. For example, if you want to attach a file to an email in ASP.NET 1.x, you need to reference a location on the disk using a file path. Makes sense right? To attach a file you must have a file. However, in ASP.NET 2.x, you add an attachment without having a file, all you need is a Stream.

    Having to reference the hard disk for an attachment was particularly annoying when you where generating the attachment at the same time you generated the email. For example, if the email was a message that contain a sales receipt as the attachment, and both where being generated from the web page. The annoying part was that you were sending an email, and it would be nice if you could "attach" the in-memory file without having to write it to disk.

    In order to successfully write the attachment to disk you need to handle a couple of tricky issues:

    1. Your ASP or ASP.NET page had to have permissions to write and read from the hard disk. This usually has to be arranged with IT and it made the complexity of setting up the web site on another server a degree more difficult.
    2. Not only must you have permissions to write to the hard drive, you need to make sure that you write the attachment outside of the web root (and all virtual directories) to prevent errant web requests from being able to view the attachments. This usually makes IT tear their hair out worrying about security issues.
    3. Each attachment needs a unique name so that it doesn't conflict with other attachments. This can be a dilemma since the name of the file on the hard drive is the name of the file in the email. If the name is too random, the recipient will not want to open it. If it is too structured, you risk having it conflict with another file.
    4. You needed to delete the file from the disk after the email was sent. Otherwise the hard disk would fill up from attachment files (causing complete balding in IT). On top of that you need to make sure to delete the file, even if the sending of the file failed -- i.e. handle the error cases correctly.

    Dealing with all these issues was trickier than the actual sending of the email and always caused me to sigh and wish I could just attach the memory allocated and formatted for the attachment directly to the email, naming it whatever I wanted. Some smart person at Microsoft thought of just that with ASP 2.x and now you can attach a Stream to a file. And since a MemoryStream is a Stream we can attach directly from memory.

    MemoryStream

    The name "Streams" defines a set of classes in CLR that are derived from the Stream class. My favorites are FileStream and MemoryStream. The Stream class defines how subclasses should behave -- the stream class itself is an abstraction for a sequence of bytes. Streams can be manipulated in many ways, however using a TextWriter or BinaryWriter makes it much easier. A MemoryStream is just an allocation of memory to hold your data sequence. It contains a position pointer and Reader and Writer classes can add bytes or read bytes from the position. Writing to a MemoryStream is no different then writing to a FileStream. Here is an example of writing a file to the hard disk and attaching it to email using C# in .NET 1.1

    using System.Web.Mail;

    String filename = Server.MapPath("/test.txt");
    FileStream filestream = new FileStream(filename, FileMode, FileAccess);
    StreamWriter streamwriter = new StreamWriter(file);
    streamwriter.Write("Hello world!");
    streamwriter.Close();
    filestream.Close();

    MailMessage msgMail = new MailMessage();

    msgMail.To = "webmaster@15Seconds.com";
    msgMail.From = "someone@somedomain.com";
    msgMail.Subject = "Attachment Test";

    msgMail.BodyFormat = MailFormat.Text;
    msgMail.Body = "Check out the attachment!";
    msgMail.Attachments.Add(new MailAttachment(filename));

    SmtpMail.Send(msgMail);

    Notice the threading issue. If we are reusing test.txt and there are many requests, then the file might be overridden by one use before it is sent by a previous user. There might also be file access issues since the file is being read and written to at the same time.

    We can solve this problem in .NET 1.1 by changing the file name, the easiest way is to use a GUID:

    Guid guid = new Guid();
    String filename = Server.MapPath("/" + guid.ToString() + ".txt");

    However, when the user gets the email, it will have the guid name, a name that isn't associated with the content.

    Also notice that we are not deleting the attachment. The code for removing the attachment might look like this:

    Guid guid = new Guid();
    String filename = Server.MapPath("/" + guid.ToString() + ".txt");

    try
    {
        // ... code to create attachment and send email.
    }
    finally
    {
        if (File.Exists(filename))
            File.Delete(filename));
    }

    We need to execute the delete inside the finally since we always want to clean-up the file even if there is an exception. However, now that we have added the try we need to add our own error handling.

    .NET 2.0

    .NET 2.0 comes to the rescue by allowing us to attach any class derived from the Stream class -- including Memory Stream. For example:

    using System.Net.Mail;

    MemoryStream memorystream = new FileStream();
    StreamWriter streamwriter = new StreamWriter(file);
    streamwriter.Write("Hello world!");
    streamwriter.Close();

    Notice that we don't have a filename, this is because the stream exists only in RAM. However, we still use the StreamWriter, just like we did when we used the FileStream object.

    Now we use the whole new object structure for .NET 2.0 located in the namespace System.Net.Mail:

    MailMessage Message = new MailMessage();

    Message.Subject = "Attachment Test";
    Message.Body = "Check out the attachment!";
    Message.To.Add("webmaster@15Seconds.com");
    Message.From = "someone@somedomain.com";

    Message.Attachments.Add(new Attachment(memorystream, "test.txt", MediaTypeNames.Application.Text));

    Notice that we created the attachment from the MemoryStream and we got to name the attachment anything we want. The name of the attachment in the second parameter is the name of the file in the email, not the name on the local system hard drive. In fact the attachment never goes to the local hard drive. The third parameter is the Mime type of the attachment, in our case this is text.

    Summary

    The RAM that is used for the Memory Stream gets released when the garbage collector cleans up the Memory Stream object. In the case of ASP.NET, that is sometime after the response is finished. The garbage collector for .NET is much more efficient way of "cleaning up" the attachments then writing our own code to delete files from the hard drive.

    Because we are not using the hard drive with the memory stream, we don't need special permissions to create files on the hard drive. IT doesn't need to configure the permissions of the .aspx page, nor the NTFS ACLs.

    Because we are not using a fixed file path, there are no threading conflicts and we can send the file with any file name we want.

    RAM is also much faster then disk IO, so the attachment will generate faster and be sent faster then if we had to write to disk.

    The code to implement and the considerations needed to implement are greatly reduced, making a memory stream attachment a more secure, faster, and easier solution.

    About the Author

    Wayne Walter Berry founded Sign Me Up Marketing in 1996. As with all start-up companies, Berry is responsible for the design, product development, and strategy that drives this innovative high-tech company.

    As a former Microsoft design engineer, and the director of development for FreeShop, Berry's expertise includes software design, development, marketing and online business. The web site he created as a hobby to assist in distributing information to Active Server Page developers became his first product, 15 Seconds. The recent sale of 15 Seconds to Internet.com allowed Berry time to develop his latest product, XBuilder, and Kulshan.com, a community web-site for his hometown, Bellingham, Washington.

    The Bellingham native graduated from Bellingham High School, and Western Washington University with a BS in computer science. Berry is the author of three books, ActiveX Unleashed Programming, Windows Registry Guide, and Special Edition - Using Microsoft Internet Information Server 4.0. A popular and respected speaker, Berry recently spoke to the Professional ASP Developers Conference in Denver and has been invited to speak to an international ASP conference in Sweden.

  • Rate This Article
    Not HelpfulMost Helpful
    1 2 3 4 5
    Other Articles
    Jul 21, 2005 - N-Tier Web Applications using ASP.NET 2.0 and SQL Server 2005 - Part 1
    While the .NET Framework made building ASP.NET applications easier then it had ever been in the past, .NET 2.0 builds on that foundation in order to take things to the next level. This article shows you to how to construct an N-Tier ASP.NET 2.0 Web application by leveraging the new features of ASP.NET 2.0 and SQL Server 2005.
    [Read This Article]  [Top]
    Apr 28, 2005 - New Files and Folders in ASP.NET 2.0
    With the release of ASP.NET 2.0, Microsoft has greatly increased the power of ASP.NET by introducing a suite of new features and functionalities. As part of this release, ASP.NET 2.0 also comes with a host of new special files and folders that are meant to be used to implement a specific functionality. This article examines these new files and folders in detail and provides examples that demonstrate how to utilize them to create ASP.NET 2.0 applications.
    [Read This Article]  [Top]
    Mar 10, 2005 - The DataSet Grows Up in ADO.NET 2.0 - Part 2, Cont'd
    Alex Homer continues his detailed look at the major changes to the DataSet class. In this part, he looks at two features that allow developers to work with data in a more structured and efficient way when using the DataSet with a SQL Server 2005 database server.
    [Read This Article]  [Top]
    Mar 9, 2005 - The DataSet Grows Up in ADO.NET 2.0 - Part 2
    Alex Homer continues his detailed look at the major changes to the DataSet class. In this part, he looks at two features that allow developers to work with data in a more structured and efficient way when using the DataSet with a SQL Server 2005 database server.
    [Read This Article]  [Top]
    Mar 3, 2005 - The DataSet Grows Up in ADO.NET 2.0 - Part 1, Cont'd
    In this article, Alex Homer looks at the changes between the version 1.x and version 2.0 DataSet and their associated classes, showing you how you can take advantage of the new features to improve your applications' capabilities and performance.
    [Read This Article]  [Top]
    Mar 2, 2005 - The DataSet Grows Up in ADO.NET 2.0 - Part 1
    In this article, Alex Homer looks at the changes between the version 1.x and version 2.0 DataSet and their associated classes, showing you how you can take advantage of the new features to improve your applications' capabilities and performance.
    [Read This Article]  [Top]
    Feb 16, 2005 - Writing a Custom Membership Provider for the Login Control in ASP.NET 2.0
    In ASP.NET 2.0 and Visual Studio 2005, you can quickly program custom authentication pages with the provided Membership Login controls. In this article, Dina Fleet Berry examines the steps involved in using the Login control with a custom SQL Server membership database.
    [Read This Article]  [Top]
    Dec 29, 2004 - ClickOnce Deployment in .NET Framework 2.0
    In this article, Thiru Thangarathinam examines .NET 2.0's new ClickOnce deployment technology that is designed to ease deployment of Windows forms applications. This new technology not only provides an easy application installation mechanism, it also eases deployment of upgrades to existing applications.
    [Read This Article]  [Top]
    Dec 15, 2004 - A Sneak Peek at ASP.NET 2.0's Administrative Tools
    With ASP.NET 2.0, Microsoft has made great strides in increasing developer productivity and has made implementing previously complex solutions relatively easy. Where this version of ASP.NET really shines, however, is in its new administrative tools that allow developers to spend less time managing the configuration of the servers and software and more time developing great code.
    [Read This Article]  [Top]
    Nov 17, 2004 - The ASP.NET 2.0 TreeView Control
    Thiru Thangarathinam introduces ASP.NET 2.0's new TreeView control which provides a seamless way to consume and display information from hierarchical data sources. The article discusses this new control in depth and explains how to use this feature rich control in your ASP.NET applications.
    [Read This Article]  [Top]
    Mailing List
    Want to receive email when the next article is published? Just Click Here to sign up.

    Support the Active Server Industry

    internet.comearthweb.comDevx.commediabistro.comGraphics.com

    Search:

    Jupitermedia Corporation has two divisions: Jupiterimages and JupiterOnlineMedia

    Jupitermedia Corporate Info

    Legal Notices, Licensing, Reprints, Permissions, Privacy Policy.
    Advertise | Newsletters | Tech Jobs | Shopping | E-mail Offers