Tuesday, September 23, 2008

Logging to the database with Enterprise Library

Update:

I have since started my own implementation which is describered in the following articles:

================================

So I've been using the Enterprise Library's logging block since v1; however, I've always logged to mostly unstructured or semi-structured locations such as email, files or the event log. I've had a lot of success using the block for logging exception messages or basic application events.

In all the apps I've ever written I've always had a need for a more robust strongly structured data store to facilitate reporting, and I've always resorted to rolling my own. Over the years the implementations have varried from very narrowly focused systems that support a single subsystem to more generic mechanism that support a various paradigm. For example logging of the messages within an SOA environment.

  • Incoming Message
  • Outgoing message to the next service
  • Reponse from that service
  • Response to the original request.

When ever its time to implement these systems, our team would always debate if we could leverage the Enterprise Library logging block; however, we've found that it was always easier to just roll our own quick dirty logger.

Today I had to ask this question again, only this time I am a team of one so I only had myself to argue with. I want to store an audit trail when a user logs into my web application, and collect all the fun stats such as his browser. (I know I could look at the iis logs but that won't let me profile which browsers have access to certain features, without having to figure out which urls if any compose a specific feature...this can be a whole other post so I will leave it at this).

The enterprise library does support a datbase trace listener out of the bat; however, it is seriously flawed. The listener can only log to a very specifc table structure. There is no way to say, I want to add this piece of information such as the IP Address of the client to the table as a seperate field.

The table does a text field called FormattedMessage which will use an Formatter that is asociated with the listener to generate a message. So while it is possible to get my IP Address in there, it forces to fall back onto to a non-relational model such as XML. While I love this flexibility, I've seen many DBA pulling their hair out at 3:00 am when they need to pull and aggregate data from a XML blob. Since this is a text field and not the Xml Data Type, I can't really enforce a schema.

So what is a poor developer to do? Well I don't have a solution implemented yet...But I plan on creating my own database trace listener that will let you specify the parameters and how to pull the values from the LogEntry object dynamically.

If I make any progress I'll add a new post. If anyone is aware of any solutions out there let me know.

Thanks,

Josh

Saturday, September 6, 2008

Setting up a printer on Windows Home Server

I recently won an HP Home Server (I actually got it about a month ago and decided to break it out of the box today). Its amazing how much life has changed for me in 10 years with a wife and three kids. 10 years ago that server would have been unpacked and up and running within an hour of getting it.

Anyways so far I am fairly happy with how easy it has been to setup the media server. I've just finished adding my Lexmark 5495 to the server, it took me longer to find the right drivers then it did to actually install them.

My only issue with the process is that you have to use remote desktop and login to the server. The help documentation for Home Server actually advises that you do not do this. Sharing resources like a printer seems like such a common task that it would have been nice for them to find a way to integrate into the Home Server Console.

To install a printer you can simply hook the printer into the USB or Parralel port, and then one of two things will happen. Either the server will detect the printer and install the printer or you will have to do this manually. You can check if the printer was installed by going to the shared folders and you should see the printer, if you do not then you will need to do it manually.

To do this open up remote desktop and connect to the server. Then you will install the drivers just as you would on any other computer.

Once the printer is installed you can connect to it by going to \\YourServerName\Printers You will also see the printer at \\YourServerName\NameOfYourPrinter. When you right click on the printer you can select connect and it should install the drivers for you.

Enjoy
Josh

Wednesday, August 27, 2008

Bashing and Rants

Here's a good example of the problem with blogging technology. You give anyone the ability to instantly publish and your going end up with some dribble and rants.

This article is nothing but bashing of MS, and provides no substantiation of any of the claims the author makes. Give examples of good projects that have been squashed due to the giant beast gobbling up the developers and forcing them to stop working on a project.

As Oren Eini put it so nicely
Who exactly said that I owe something to anybody? Who exactly said that any of the guys who went to work for Microsoft (many of whom I consider friends) owe you something.


How dare anyone have the audacity to claim an evil doing that a developer of a free tool abandoned the project.

I guess that's the problem of free space and cheap publishing technology but now my rant about the ranters is over.

Enjoy!
Josh

Sunday, August 24, 2008

Unit Tests & Expected Exceptions

Good unit test coverage should include tests that cover the normal use cases in your code, and tests that validate any bounds are being checked. What does this mean? Take for example the following function.


public File OpenFile(string filePath)

{

Check.Require(!string.IsNullOrEmpty(filePath),"Path cannot be null or empty");

Check.Require(File.Exists(filePath), "Path must exist");

...

}




A good unit test suite will ensure that the code handles the exception cases, when the codes pre & post conditions are not met. When writting these tests you will need to watch for exceptions. One quick implementation of this is:

try

{

FileInfo file = OpenFile(null);

}

catch (PreconditionException ex){}

catch (Exception badEx)

{

Assert.Fail();

}



While this works it suffers from a critical problem that how do I know which exception we were expecting to get? Unless this is documented, I can't be certain of the original test writters intentions.

Many of the unit testing frameworks provide a solution to this with an ExpectedException (or some variant there of) attribute which can be placed on a test method. This attribute typically takes a type of exception and optionally a message that should be the message of the exception.

This is definetly better and results in a simple test in the MS Test framework such as the following:


[TestMethod]

[ExpectedException(typeof(PreconditionException))]

public void OpenFile_NullPathTest()

{

FileInfo file = OpenFile(null);

}



This works fine in this simple case, but what if we have a more complex test, or we are doign an integration test and testing lots of components. If any component throws the exception then your test will still pass.

A better way would let us both clearly express the intent of the test, and to narrow down a specific line or set of lines that should generate the exception.

In C# 3.0 we can leverage delgates and extension methods to come up with a simple way that achieves these goals. Our test method now looks like:



[TestMethod]

public void OpenFile_NullPathTest()

{

Action action=delegate{ OpenFile(null); };

action.ExpectedException(typeof(PreconditionException));

}




This test clearly states that the OpenFile(null) call will result in a PreconditionException, and if there is other stuff occuring within the test, we don't have to worry about the test passing when it should have passed.

The ExpectedException method is an extension method on an Action Delegate. Action is a general delegate that takes no arguments and returns a void. To use this you need to add the following method to a static class, and make sure that the class is within a referenced name space (using in C# or imports in vb).



public static void ExpectedException(this Action action, Type expectedException)

{

try

{

action();

Assert.Fail("Expected exception did not occur");

}

catch (Exception ex)

{

Assert.AreEqual(expectedException, ex.GetType(), string.Format("Expected exception of type {0} but recieved exception of {1}", expectedException.Name, ex.GetType().Name));

}

}



This method could be enhanced to allow checking that the right exception is thrown but that the message is what you expect; however, I'll leave that as an exercise for you.

If your not a big fan of extension methods you could do this using a delegate or even nicer with a lamba such as:
TestHelper.ExpectedException(() => OpenFile(null),typeof(PreconditionException));

Enjoy!

Josh

Edited: 11-17-2008 Added an Assert.Fail() after we call the action delegate in our test helper.

Wednesday, August 20, 2008

Overidding a javascript method

As I'm forced to spend more time doing client web development, I'm finding javascript to be an interesting language to work. Recently I've discovered a fun way to override a method on a javascript object that I would like to share.

Let's take the following example:

function apple(color)


{


this._color=color;


}



apple.prototype.AlertColor=function()


{


alert(this._color);


}



var myApp=new apple("red");


myApp.AlertColor();




When you run this inside a web page you'll get an alert box with the color red. Now let's pretend that our apple is an external script, which is used in many web pages; however, in one specific page we need to change the functionality of the AlertColor method. How do we do this?


apple.prototype.AlertColor=function()


{


alert("blue");


}



var myApp=new apple("red");


myApp.AlertColor();




What we are doing here is replacing the definition of AlertColor on all instances of apple with our new function. Running this script will give you an alert of blue. Let us go one step further and pretend that we want to wrap custom functionality around the AlertColor function.


apple.prototype.Original_AlertColor=apple.prototype.AlertColor;



apple.prototype.AlertColor=function()


{


alert("You are asking about the color well I am...");


this.Original_AlertColor();


}



var myApp=new apple("red");


myApp.AlertColor();




Here you will get two alert boxes. What we have essentially done is add a new function called Orginal_AlertColor and we set to the orginal AlertColor function. Then with our new function we call the original function.

Now that hopefully we understand the basic how to, what can I do with this? Here are some examples I've found in the wild:
  • TextBoxWatermark Extender in Ajax Control toolkit uses this approach to replace the default ASP.Net function for submitting a form. They use this to blank out the watermarked text before posting back to the server.
  • Component Art recommends using this to replace the standard window.alert() method which they use to spit out debug information.

Enjoy!