kamagra how much to take

WebPart Exception / Error Handling

I got asked today what I use for WebPart exception handling / error handling, and I think this may be my first embrassing code post (I think?), with many more to follow, I’m sure. Well, I actually thought it was embrassing, then I read this right before I am posting this:

http://www.codeproject.com/useritems/Errorhandling_in_Webparts.asp

Wow, that’s profound. :)

If it is available and organizationally acceptable I usually go the route of using the Enterprise Library Exception Handling Application Block from MSFT since I think it is great for management and quick configuration changes (and hell, it’s already written), and I really like how all the plumbing is taken care of behind-the-scenes. Since a lot of times organizations prefer custom exception handling classes (for what, I do not know, since you end up re-writing what is already done in the ELEHA) I use an internal class in a generic shared library for exception handling stuff.

This by no means implies that the route I take for exception handling is the right one, in fact, it could probably be improved greatly. Because there are 50,000 blog posts / best standards documents for .NET already on exception handling, hell people do .NET debugging / error handling for a living (that actually sounds like an awful job), I am not really going to dip into the specific of how the code works or profess that this is the best practice available.
My GenericExceptionHandler.cs class is demonstrated at the bottom of this post, I use the route of both creating and writing to a new event source for WebParts to take advantage of the MOSS web event viewer (good for hosting environments), as well I usually write to the executing assembly directory with a custom little text log file with the problems that are encountered (bad for hosting environments).

If you don’t care about the little tidbits on how to use it, since it is pretty straightforward and you can just infer the functionality from the code, just scroll to the bottom, copy and paste, you are ready to rock and roll.
For the rest….

Obviously for some remedial event handling, it doesn’t make utter sense to use this approach, so I just go the standard route of:

  1. catch (Exception exception)
  2. {
  3. output.Write("" + exception.ToString() + "");
  4. continue;
  5. }

In other cases I want to house error in a different medium, in which case I call this class. How do I call this class you ask Batman? There are a couple of different ways, most of them you can infer from the code. Otherwise, let me take the example of our rudimentery exception handling above, which if modified would look something like (or a variation of as you will see when you see the generic exception handler class) this:

  1. catch (Exception exception)
  2. {
  3. GenericExceptionHandler.WriteLine(TraceLevel.Error, "Your Error Text" + exception.ToString(), "YourClassName");
  4. return;
  5. }

You could even set up conditions to test the TraceLevel before doing any work such as writing an event to your event source. This would look like:

  1. if (GenericExceptionHandler.TraceLevel == TraceLevel.Verbose)
  2. {
  3. GenericExceptionHandler.WriteLine(TraceLevel.Verbose, "I am doing something on:" + myString, "YourClassName);
  4. }

You can also create your own exception classes the generic exception handling after an intial custom exception satisfaction is fufilled. Meaning, you could do something like create a new exception handling class for your WebPart that would inherit from the ApplicationException base class so that you could capture non-fatal errors.

  1. using System;
  2.  
  3. namespace arb.Generic.SharedLibrary.exceptionHandling
  4. {
  5. internal class myGreatException : ApplicationException
  6. {
  7. internal myGreatException()
  8. {
  9. }
  10.  
  11. internal myGreatException(string message) : base(message)
  12. {
  13. }
  14.  
  15. internal myGreatException(string message, Exception inner) : base(message, inner)
  16. {
  17. }
  18.  
  19. }
  20. }

Once you have the ApplicationException derived class defined, you can then call the class to bind an exception in your code, and then use the GenericExceptionHandler in order to do whatever you like!

  1. catch (myGreatException exception)
  2. {
  3. GenericExceptionHandler.WriteLine(TraceLevel.Error, "I am doing something" + exception.ToString(), "YourClassName");
  4. }

One of the things that I like to use about this class is also you can write important information as it occurs when you are using it, in something like a method that you call:

  1. public static void myWebPartMethod()
  2. {
  3.  
  4. GenericExceptionHandler.WriteImportantInfoLine("Your Method Is Starting", "YourClassName");
  5.  
  6. }

Or, of course, you can write the same type of thing with verbose information:

  1. public static void myWebPartMethod()
  2. {
  3.  
  4. GenericExceptionHandler.WriteImportantVerboseLine("Your Method Is Ending", "YourClassName");
  5.  
  6. }

Neat! When working with the logging features provided by the class, you should also learn how to start and dispose of the actual logging process. Typically, you start the logging in a constructor or something. Here is an example:

  1. public class testLogging
  2. {
  3. static testLogging()
  4. {
  5. GenericExceptionHandler.StartLogging();
  6.  
  7. }
  8. }

Then in order to teardown logging, you can combine what we have seen this far with the StopLogging() method as provided by the GenericExceptionHandler class. You can write the information out, and then stop the actual logging. This will maintain a good inventory of what the hell is going on with your WebPart.

  1. public static void StopLogging()
  2. {
  3. GenericExceptionHandler.WriteImportantVerboseLine("I want to stop logging por favor", "YourClass");
  4. GenericExceptionHandlerStopLogging();
  5. }

Wow. We have talked a lot about how to use the class, but we haven’t even looked at the class yet. I think I got carried away. The class is below. There are some important .NET concepts that are introduced with it, that I briefly explain below:

Trace class – provides the methods that we require to instigate tracing in the WebPart code.

TraceLevel – used to declare trace message output

TextWriterTraceListener – this is used to writes trace output to some file.

TraceSwitch – This is pretty important. TraceSwitch allows you to control tracing however withouth recompilation, meaning, the TraceSwitch object has a level property that you can set to whatever, from Off to Verbose. It works in a snowball scenario, if you set to a middle tier of tracing, all sub tiers are included in your tracing.

EventLog – Supplies ways to work with the Windows event logs

EventLogEntryType – Enumeration that defines the event log type

That is pretty much all the knowledge you need to be equipped with to understand the class. Feel free to use in your own applications, I don’t really care what you do with it.

//*****************************************************************************
// This code file is part of the Example WebPart Exception Handling
// This file was written by Adam Buenz [WSS MVP] of ARB Security Solutions, LLC
// http://www.sharepointsecurity.com
//
// This is a generic exception handling class file that is
// is meant to allow both writing of events to both the a text
// file in the executing assembly directory as well as creating
// an event source if it doesn’t exist to write errors to there
// as well.
//
// This file and its parts is free for re-distribution, for use in both free
// and commercial applications, however this header must remain intact for legal
// use. This class file is distributed in the hope that it will
// be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
//*****************************************************************************
//**************************************
// Current Version: 1.0.0.0 (Production)
//**************************************

using System;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Xml;

namespace arb.Generic.SharedLibrary.exceptionHandling
{
internal class GenericExceptionHandler
{
private static int _keepLogForXDays;
private static TextWriterTraceListener _listener;
private const string _logFieldDateFormat = “yyyyMMdd_HHmmss”;
private static Stream _logFile;
private const string _logFileName = “ExampleLogFile_”;
private static TraceSwitch traceSwitch;

internal static int KeepLogForXDays
{
get
{
return GenericExceptionHandler._keepLogForXDays;
}
set
{
GenericExceptionHandler._keepLogForXDays = value;
}
}

internal static System.Diagnostics.TraceLevel TraceLevel
{
get
{
return GenericExceptionHandler.traceSwitch.Level;
}
set
{
GenericExceptionHandler.traceSwitch.Level = value;
}
}

static GenericExceptionHandler()
{
GenericExceptionHandler.traceSwitch = new TraceSwitch(“SharePointServer”, “Tracing for Your WebPart”);
GenericExceptionHandler._keepLogForXDays = 5;
}

private static void closeLogFile()
{
Trace.Flush();
GenericExceptionHandler._listener.Flush();
GenericExceptionHandler._listener.Close();
Trace.Listeners.Remove(GenericExceptionHandler._listener);
GenericExceptionHandler._logFile.Close();
}

internal static void FlushLogFile()
{
GenericExceptionHandler.closeLogFile();
GenericExceptionHandler.setupLogFile();
GenericExceptionHandler.removeOldLogFiles();
}

private static void removeOldLogFiles()
{
try
{
DateTime curATime = DateTime.Now.AddDays((double)(GenericExceptionHandler._keepLogForXDays * -1));
string[] fArray = Directory.GetFiles(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), “LogFile_*.log”);
foreach (string lFile in fArray)
{
try
{
int lLength = lFile.IndexOf(“LogFile_”) + “LogFile_”.Length;
if (lLength > 0)
{
int calcLength = (lFile.Length – lLength) – 4;
string getLength = lFile.Substring(lLength, calcLength);
DateTime repTimeMod = DateTime.ParseExact(getLength, “yyyyMMdd_HHmmss”, CultureInfo.InvariantCulture);
if (repTimeMod.CompareTo(curATime) < 0) { File.Delete(lFile); } } } catch (Exception exception) { GenericExceptionHandler.WriteLine(System.Diagnostics.TraceLevel.Error, “An error has occured in the removeOldLogFiles method(” + lFile + “) : ” + exception.ToString(), “GenericExceptionHandlerClass”); } } } catch (Exception exception) { GenericExceptionHandler.WriteLine(System.Diagnostics.TraceLevel.Error, “An error has occured in the removeOldLogFiles method: ” + exception.ToString(), “GenericExceptionHandlerClass”); } } private static void setupLogFile() { string nPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + @”\LogFile_” + DateTime.Now.ToString(“yyyyMMdd_HHmmss”) + “.log”; GenericExceptionHandler._logFile = File.Create(nPath); GenericExceptionHandler._listener = new TextWriterTraceListener(GenericExceptionHandler._logFile); Trace.Listeners.Add(GenericExceptionHandler._listener); } internal static void StartLogging() { GenericExceptionHandler.setupLogFile(); GenericExceptionHandler.removeOldLogFiles(); } internal static void StopLogging() { GenericExceptionHandler.closeLogFile(); } private static void WriteEventLog(System.Diagnostics.TraceLevel TraceLevel, string Message) { EventLogEntryType callMEntry; switch (TraceLevel) { case System.Diagnostics.TraceLevel.Error: callMEntry = EventLogEntryType.Error; break; case System.Diagnostics.TraceLevel.Warning: callMEntry = EventLogEntryType.Warning; break; default: callMEntry = EventLogEntryType.Information; break; } if (!EventLog.SourceExists(“MyWebPart”)) { EventLog.CreateEventSource(“MyWebpart”, “Application”); } EventLog sharepointSignalLog = new EventLog(); sharepointSignalLog.Source = “MyWebPart”; sharepointSignalLog.WriteEntry(Message, callMEntry); } internal static void WriteImportantInfoLine(string Message) { Trace.WriteLine(DateTime.Now.ToString() + ” : ” + Message); GenericExceptionHandler.WriteEventLog(System.Diagnostics.TraceLevel.Info, Message); } internal static void WriteImportantInfoLine(string Message, string Category) { Trace.WriteLine(DateTime.Now.ToString() + ” : ” + Message, Category); GenericExceptionHandler.WriteEventLog(System.Diagnostics.TraceLevel.Info, Category + “: ” + Message); } internal static void WriteImportantVerboseLine(string Message) { Trace.WriteLine(DateTime.Now.ToString() + ” : ” + Message); } internal static void WriteImportantVerboseLine(string Message, string Category) { Trace.WriteLine(DateTime.Now.ToString() + ” : ” + Message, Category); } internal static void WriteLine(System.Diagnostics.TraceLevel TraceLevel, string Message) { GenericExceptionHandler.WriteLine(DateTime.Now, TraceLevel, Message); } internal static void WriteLine(DateTime time, System.Diagnostics.TraceLevel TraceLevel, string Message) { int nLevel = (int)TraceLevel; if ((nLevel <= 2) || (((System.Diagnostics.TraceLevel)nLevel) <= GenericExceptionHandler.traceSwitch.Level)) { Trace.WriteLine(time.ToString() + ” : ” + Message); } if ((nLevel != 4) && (((System.Diagnostics.TraceLevel)nLevel) <= GenericExceptionHandler.traceSwitch.Level)) { GenericExceptionHandler.WriteEventLog(TraceLevel, Message); } } internal static void WriteLine(System.Diagnostics.TraceLevel TraceLevel, string Message, string Category) { GenericExceptionHandler.WriteLine(DateTime.Now, TraceLevel, Message, Category); } internal static void WriteLine(DateTime time, System.Diagnostics.TraceLevel TraceLevel, string Message, string Category) { int nLevel = (int)TraceLevel; if ((nLevel <= 2) || (((System.Diagnostics.TraceLevel)nLevel) <= GenericExceptionHandler.traceSwitch.Level)) { Trace.WriteLine(time.ToString() + ” : ” + Message, Category); } if ((nLevel != 4) && (((System.Diagnostics.TraceLevel)nLevel) <= GenericExceptionHandler.traceSwitch.Level)) { GenericExceptionHandler.WriteEventLog(TraceLevel, Category + “: ” + Message); } } } }[/csharp] So that is my exception handling class. Again, I am not saying it is a right or wrong one, its just one I use, and after I saw that post on CodeProject, yeesh. :) I would be interested to hear about what others use for their WebPart exception handling. Maybe someone would want to work on a best practices document with me?

Share

18 Comments

  1. IHTB says:

    Hey, I think you are the smartest Sharepoint developer on the planet!

  2. Ur@ says:

    Have try it, but I get Sharepoint-Error “WP or WebControl can not be displayed or imported on this Page. The Type is not registered as secure” (original Error-Message in german “Ein Webpart oder Webformular-Steuerelement auf dieser Seite kann nicht angezeigt oder importiert werden. Der Typ ist nicht als sicher registriert”).
    My HelloWorld-WP:

    public class HelloWorld : WebPart
    {
    protected override void Render(System.Web.UI.HtmlTextWriter writer)
    {
    try
    {
    writer.WriteLine(“Hello”);
    }
    catch (Exception ex)
    {
    if (GenericExceptionHandler.TraceLevel == TraceLevel.Verbose)
    {
    GenericExceptionHandler.WriteLine(TraceLevel.Verbose, “I say Hello” + ” “, “HelloWorld”);
    }
    GenericExceptionHandler.WriteLine(TraceLevel.Error, “ErrorText: ” + ex.ToString(), “HelloWorld”);
    return;
    }
    }
    }

  3. Ur@ says:

    …and in my web.config i have this entry:

    GenericExceptionHandler and HelloWorld are included to the Namespace “MyWebPartsNS”

  4. Ur@ says:

    web.config entry (once again, because unavailable preview on this page):
    SafeControl Assembly=”FabCWebParts, Version=1.0.0.65, Culture=neutral, PublicKeyToken=8c3097a972539e18″ Namespace=”FabCWebParts” TypeName=”*” Safe=”True”

  5. Ur@ says:

    sorry for overflooding, I mean web.config have that:
    SafeControl Assembly=”MyWebPartsNS, Version=1.0.0.0, Culture=neutral, PublicKeyToken=MyPublicKey” Namespace=”MyWebPartsNS”

    … and Bob Mixon have proposed another suggestion for Error-Handling, http://microsoftd2d.com/archives/SH020507.html

  6. Adam Buenz says:

    Sorry, however that type error is one that I haven’t seen before. Being that I don’t know German well enough to translate the error, are you sure it doesn’t say:

    “A Web Part or Web Form Control on this Web Part Page cannot be displayed or imported because it is not registered on this site as safe.”

    because in your last entry which stated:

    SafeControl Assembly=”MyWebPartsNS, Version=1.0.0.0, Culture=neutral, PublicKeyToken=MyPublicKey” Namespace=”MyWebPartsNS”

    the entry is not decorated with the Safe=”True” attribute.

    If you would like, send me your solution file, and I will help you through it as well. My inclination is it doesn’t have anything to do with the generic exception handling class file, however we can work through it!

  7. Ur@ says:

    Hello Adam, yes it was “because it is not registered on this site as safe”.
    Sorry for long silence, but i still want (and need) start to use your solution.

    I’m just to newbie in .net and sharepoint programming, so i have try to use it just in helloWorld-Example outside from WebPart’s and SP2007 and just for my understanding what that is. After execution of followed Code I can’t find the Log-File. Where is this Location for Assembly.GetExecutingAssembly().Location?

    Here is my code:
    using System;
    using System.Diagnostics;
    using System.Text;

    namespace Test
    {
    public class Program
    {
    static void Main(string[] args)
    {
    GenericExceptionHandler.StartLogging();
    try
    {
    Console.WriteLine(“Hello”);
    GenericExceptionHandler.WriteLine(TraceLevel.Verbose, “I say Hello” + ” “, “HelloWorld”);
    }
    catch (Exception ex)
    {
    GenericExceptionHandler.WriteLine(TraceLevel.Error, “Error Text: ” + ex.ToString(), “HelloWorld”);
    return;
    }
    finally
    {
    GenericExceptionHandler.WriteImportantVerboseLine(“I want to stop logging “, “TestError”);
    GenericExceptionHandler.StopLogging();
    }
    }
    }
    }

  8. Adam Buenz says:

    No problem, I can help you with it.

    I believe you are looking for the right method, in setupLogFile().

    private static void setupLogFile()
    {
    string nPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + @”\LogFile_” + DateTime.Now.ToString(“yyyyMMdd_HHmmss”) + “.log”;
    GenericExceptionHandler._logFile = File.Create(nPath);
    GenericExceptionHandler._listener = new TextWriterTraceListener(GenericExceptionHandler._logFile);
    Trace.Listeners.Add(GenericExceptionHandler._listener);
    }

    Assembly.GetExecutingAssembly().Location in its full form is System.Reflection.Assembly.GetExecutingAssembly.Location(), and it reflects on the assembly and gets the directory that it is executing from in order to build up the log files.

    Therefore, you should be finding the log files in the directory that your code is running from (Generally, this will be in Your Project – > Bin – > Debug under the default VS.NET settings.

  9. Ur@ says:

    Thank You,
    I was not attentive and search it inside Folder for another Project.

    But what about GenericExceptionHandler.WriteLine()
    How i can read (EventLog) sharepointSignalLog within eventvwr.msc?

  10. Ur@ says:

    or where i can read it usually?

  11. Adam Buenz says:

    Hello,

    Generally, you should be able to read it through the Event Log MMC snap-in that you are referring to. Meaning, you should see the code that creates the event source out of the System.Diagnostics that looks like this:

    if (!EventLog.SourceExists(mySource))
    {
    EventLog.CreateEventSource(mySource, myLog);
    }

    Where it is checking if the event source exists and then creating it if it does not. Specifically, the event source should be created in this code in the above example:

    if (!EventLog.SourceExists(“MyWebPart”))
    {
    EventLog.CreateEventSource(“MyWebpart”, “Application”);
    }

    Then you should see the actual events being written using WriteEntry.

    EventLog.WriteEntry(mySource, myEvent);

    Is there a specific problem that you are having or are you seeing that the event source is not being created for some reason.

  12. Ur@ says:

    Hello Adam,

    yes, I understand that it should be in Application-Channel of EventViewer. But what does that mean with preconditions in WriteLine-Method, e.g.:
    if ((nLevel

  13. Ur@ says:

    (Once again)
    Hello Adam,
    yes, I understand that it should be in Application-Channel of EventViewer. But what does that mean with preconditions in WriteLine-Method, e.g.
    if nLevel

  14. Ur@ says:

    oooh… how long is msg.maxLenght here?
    (… continuing..)
    Specially how can nLevel be lower GenericExceptionHandler.traceSwitch.Level?
    With other words, I dont understand in what cases Exceptions should be written to EventLog.
    And many, many thanks for Your patience and assistance

  15. Ur@ says:

    Hello Adam,
    I apologize if You already alergical to my stupid? questions.
    Firstly i should say, that Your solution work :) Partially, but works (YMMV).

    Sorry, I still don’t understand this condition “if nLevel

  16. Ur@ says:


    Sorry, I still don’t understand this condition “if nLevel LessThen GenericExceptionHandler.traceSwitch.Level”. So I use only txt Logging, it sufficient.

    However, I think about how I can start Logging as soon as possible. I trying to start it on Init-Event:

  17. Ur@ says:


    HelloWorld() : base() { this.Init += new EventHandler (myErrorHandler); }
    private void myErrorHandler(object sender, System.EventArgs e) { GenericExceptionHandler.StartLogging(); }

    but that do not work – SharePoint dont display HelloWorld-WebPart in Catalog/New.
    So I start Logging in Render(writer), and its work fine, I get my LoggFile. But what if I get Exception in Initializaton? What can I do better?

  18. Adam Buenz says:

    Sorry, busy week for me!

    In regards to your question to the nLevel field. If you look here:

    int nLevel = (int)TraceLevel;

    Using this, a threshold can be declared for the tracelevel. i.e.
    int nLevel = (int)TraceLevel.Verbose;

    In this way, it is responsible for representing the trace level at which logging should occur.

    Does that make more sense?

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>