I ran across this cool little feature of the System.Net.Mail.SmtpClient class where you can tell it that an email sent should get dumped to a directory as a .EML file instead of being sent to a SMTP server.

This is a really cool feature for DEV/QA environments where you don't always have a SMTP server that you can test against, but have code that sends email that you need to make sure its working.  I could have used this a few times where I accidentally sent out a few emails while testing that I didn't mean to.

In your Web.config file, or App.config, add the following under <configuration>

        <smtp deliveryMethod="SpecifiedPickupDirectory">
            <specifiedPickupDirectory pickupDirectoryLocation="C:\maildump\" />


Now, when you create a MailMessage and send it through the SmtpClient, the email will be created as an .EML file in the directory you specified.

I am actually using this on my blog right now so that when people email me I don't have to have a SMTP server to have their messages sent through, I can just look at dump directory at the emails.

Posted in:   Tags:


At a client site that I am at they are coming from a Java background, so we're using a lot of 3rd party .Net libraries etc. that step from their Java counterparts.  Once such library is Log4Net, which in case you don't know, is a logging library that lets you log messages from you apps to a variety of different sources.  A few of the sources are text files, MS SQL, Oracle, SQL Lite, SMTP, etc.  Check out the Log4Net site for a list of all the options which you can log to. 

What I've come to find as of late though is that once you get these libraries working, they work great and can really add benefit to your applications.  BUT I've found setting up these libraries can be a royal pain in the ass, not to mention take quite a few hours before you get them working correctly.  Originally I was blaming the libraries for their confusing documentation, lack of "beginner" explanation etc.  The more I think about it though the more I tend to think that it has something to do with .NET as well.  Since there are so many different project types (Web apps, Console Apps, WinForms apps, etc.) and configuration methods, it is hard to provide examples/setup information for all the different project types.


Required Files

First you'll have to grab the latest version of Log4Net (at the time of this posting it was log4net 1.2.10)



Extract the zip file to a location of your liking


Project Setup

Web Application Example

  • Create a new Web Site (or Web Application)
  • Right click on the solution and select "Add Reference"
  • Select the log4net.dll under the following directory ..\log4net-1.2.10\bin\net\2.0\release
  • Right click on the reference you just added, log4net.dll, and under properties make sure that "Copy Local" is set to true (this is the step that I knew, but forgot to do and caused myself a huge headache)
    • If you installed log4net into the GAC, this step would be unnecessary
  • Add a configuration section into your Web.Config
  • This will instruct ASP.NET to use the log4net library to read the configuration information you will put further down in the <log4net> section
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
  • Add the following below your <configSections>  The point here is to create the information that log4net will read and use to configure itself and the type of logging mechanism you want to use (in this example, we're using a RollingFile appender)
  <appender name="RollingFile" type="log4net.Appender.RollingFileAppender">
    <file value="c:\temp\web.log" />
    <appendToFile value="true" />
    <maximumFileSize value="1024KB" />
    <maxSizeRollBackups value="10" />
    <layout type="log4net.Layout.PatternLayout">
      <conversionPattern value="%date %level %logger - %message%newline" />
    <level value="ALL" />
    <appender-ref ref="RollingFile" />
  • There are 2 sections here to mention
    • <appender>
      • This tells log4net which logging mechanism to use, in our case we're using a RollingFile appender and specifying the file to log to, "C:\temp\web.log"
      • We also specify how large for the file to grow before it "Rolls", meaning that it will create a new file.
      • I won't get into the <conversionPattern> settings right now, check the documentation on the log4net site for more details
      • You will most likely have to give the ASPNET account modify permissions to the directory.
    • <root>
      • This sets the "defaults" for log4net
      • We specify that log4net should log "ALL" messages.  We could also just specify "DEBUG,INFO,WARN,ERROR,FATAL"
      • In addition to the level, we specify that the default appender to use is the "RollingFile" that we specified above.
  • adf
  • Now that we've setup all the configuration information we can go ahead and start logging inside our application

using log4net;
namespace Log4NetTest
    public partial class _Default : System.Web.UI.Page
        protected void Page_Load(object sender, EventArgs e)
                //tell log4net to load the configuration, it will load the configuration info from the web.config, ideally this should be in the global.asax
                //get an instance of the logger so that we can log our messages to it.
                //it will log to which every logging mechanism you setup in the web.config
                ILog log = LogManager.GetLogger(typeof(_Default));
                    log.Debug("This is a debug message");
            catch (Exception ex)

  • Now just run your app and once it runs you should have a file named "web.log" in your c:\temp directory.

The weird thing about log4net is that it really doesn't tell you in any way shape or form that its not setup or working correctly.  Here are a few things to check

  • Set a breakpoint on the "ILog log = LogManager.GetLogger(typeof(_Default));" line, if you view log in the quick watch, if "IsDebugEnabled", etc. are ALL set to false, then you know something isn't working correctly
  • Check permissions on the directory where your trying to write the log file to, make sure that ASP.NET has modify permissions on the directory
  • Make sure that log4.net.dll is in the bin directory of your application.  Check the properties of the reference and make sure that "Copy Local" is set to true

Ideally you'll want to configure and start the logger when the web applicaiton loads, so you should move the line "log4net.Config.XmlConfigurator.Configure();" into the Application_load event of the global.asax file.  This will ensure that the logger is always started and ready to log to.  Also, instead of the line "ILog log = LogManager.GetLogger(typeof(_Default));" you should move that as a global variable to your class like so "private static readonly ILog log = LogManager.GetLogger(typeof(_Default)); ".


There are a LOT of options with log4net that I didn't even come close to covering.  Check out the documentation as well as experiment a bit yourself and see how you can fit log4net into your application for your logging needs.


See code sample below for a pre-setup example.


      Windows Application Example

      Coming Soon...

      Console Application Example

      Coming soon...


      Log4NetTest.zip (109.71 kb)

      Posted in:   Tags:

      I finally finished commenting the code samples and cleaned up the slides a touch.  Grab everything at the bottom of this post.  I cleaned all the DLL's etc. out of the bin/obj folders so that it should email nicely as well.

      PLEASE let me know if you find any errors, etc. and I'll update the code samples.  Also, if you have any trouble with any of the code samples, feel free to contact me and i'll help you out as best as I can.

      Here's the contents of the README.TXT file I included, this way you don't have to download the zip to get the info you need to get AJAX working within SharePoint

      - Download ASP.NET 2.0 AJAX Extensions 1.0
          - (I believe if you install .NET 3.5 you'll already have this)
          - it will default install to C:\Program Files\Microsoft ASP.NET\ASP.NET 2.0 AJAX Extensions\v1.0.61025
          - will have to be installed on ALL front-end servers in your FARM
          - Optional, install the ASP.NET AJAX Control Toolkit for 34 addtional "Extenders"
      - Modify your web.config to allow for using ASP.NET AJAX
          - reference this link for the steps of what to do
          - http://msdn2.microsoft.com/en-us/library/bb861898.aspx
          - or http://sharepoint.microsoft.com/blogs/mike/Lists/Posts/Post.aspx?ID=3
      - Add a script manager to your master page (this is the easiest way for now)
          - I did this using MS Office SharePoint Designer http://YOURSITE/_catalogs/masterpage/default.master
          - I believe you can do this through WebDAV as well
      - Add an AJAX enabled WebPart to your site and test!   

      - Created my CodeCamp project as a Class Library
      - Added System.Web to allow me to work with ASP.NET Controls as objects
          - if using ASP.NET AJAX Control Toolkit "Extenders", be sure to add this DLL as a reference in your project
      - Sign assembly with a strong name key file
      - Changed the build output path to SharePoint site ("C:\Inetpub\wwwroot\wss\VirtualDirectories\30287\bin"), yours will most likely be a different port.
          - This is not recommended for production deployments, Best Practice would be to create the WebPart as a feature and deploy/install it that way.
      - add Assembly to the SafeControls in my sites Web.Config section
          - <SafeControl Assembly="CodeCampDemos, Version=, Culture=neutral, PublicKeyToken=d756758a26725440" Namespace="CodeCampDemos" TypeName="*" Safe="True" />
          - Use Reflector to get proper "Assembly=" text
      - Go into the Web Part Gallery and add each individual Web Part to my site available Web Parts
      - On main page, switched to Edit Mode, and added my WebParts as needed.


      I don't have it in the current code samples/slides, but I want to get a code sample using SmartPart which is a Web Part extension which lets you take existing User Controls that work in your ASPX web pages, and just use them unchanged in your Web Parts within SharePoint 2007.  This way you can write the User Control once and use it multiple places.  As soon as I get a code sample/demo up, I'll write up a blog posting about it cause it looks pretty helpful.



      CodeCampDemos.zip (595.84 kb)

      Posted in:   Tags:

      I ran across this link over at DotNetKicks and after reading it I basically smacked myself because I literally could have used this about a week ago on a client project where I was spitting out the time it took to upload a file to a SharePoint document library.


      Turns out there is a built in System.Diagnostics.Stopwatch class that is built into the .NET 2.0 framework.  It basically prevents you from creating a start DateTime object, starting some long running code, and doing some DateTime calculations against your original start DateTime object all in a futile attempt to find out how long a process ran.

      After looking at the example code from the link above, it doesn't seem like your saving lines of code, but it is a bit easier to use and your only technically creating 1 object, as opposed to 2.  What would be interesting is to check out the MSIL code that gets generated from each example.  Doing so might shed some light onto which methods is more "effective".

      Posted in:   Tags:
      Tony Testa posted on January 13, 2008 05:05

      Once again the Philly.Net users group put on another great Code Camp! 

      I didn't get there till about 10:30 (since I wasn't speaking till 4:10PM) so I missed the first to sessions.

      The sessions I attended were :

      • "SharePoint Disaster Recovery, Backup and more…" presented by Bob Fox
        • The description of this session caught my eye right off the bat.  Since I mostly work on the development side, DR and Backup aren't something I spend a lot of my time on.  Bob did a great job of walking you through the steps to backup and restore a farm or a single site collection.  In addition he told you the pros and cons of using the SharePoint Central Administration site versus going old school with the command line stsadm.exe.
      • "InfoPath 2007 with Visual Studio 2008" presented by Michael Lotter
        • Since I don't know much about InfoPath I figured I would attend Michael's session.  I'm glad that I did, he did a good job of going over the basics of InfoPath forms, how to build them and how to deploy them to SharePoint.  He also used Visual Studio 2008 and show you how you can use the new tools without problems (well...without any major problems).
      • "Delivering Modular SharePoint Workflow Functionality via Components" presented by David Mann
        • Since I attended 2 previous SharePoint tracks I figured I'd keep with the trend in addition, David Mann was presenting and his past presentations have been really informative.  I have to say he didn't disappoint.  He gave a really good ground up presentation of Windows Workflow.  I am definitely going to have to get his slides and code so that I can start messing around with workflow's a bit more inside SharePoint.


      My presentation went pretty well and there was a decent crowd.  I still need to work on my presentation skills a bit though.  One major thing is that I need to keep a "cheat sheet" next to me while I present.  I noticed that I kind of loose focus while I am presenting and I think that if I had a "cheat sheet" next to me it might help me keep focus and on track. 

      Afterwards all the speakers meet at a local bar near DeVry for some food and a few beers.  I had a great time meeting a few of the other speakers whom I hadn't met before.  I found out a lot of the speakers had come from other area's, some from NYC and even a few from the North Carolina area (Michael Lotter). 


      Once I get done cleaning/commenting the code samples and presentation I plan on polishing it up a bit more and possibly presenting it elsewhere.

      Posted in:   Tags:
      The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

      © Copyright 2017 Tony Testa's World