Archive

Archive for May, 2012

.NET 4.0 and first chance exceptions

May 25, 2012 2 comments

.NET 4.0 introduced a new event that is raised for every exception that is thrown in an application domain. The FirstChanceException event is raised as soon as an exception is thrown. This includes any handled and unhandled exceptions.

static void Main(string[] args)
{
	AppDomain.CurrentDomain.FirstChanceException += (sender, eventArgs) =>
	{
		Console.WriteLine("First chance exception: " + eventArgs.Exception.Message);
	};

	try 
	{
		Console.WriteLine("Before exception.");
		throw new Exception("Some error.");
	}
	catch
	{
		Console.WriteLine("Handled.");
	}
}

This code will produce the output:

Before exception.
First chance exception: Some error.
Handled.

However, if an exception is thrown within the event handler, the FirstChanceException event will be raised recursively. The code below will cause a stack overflow:

static void Main(string[] args)
{
	AppDomain.CurrentDomain.FirstChanceException += (sender, eventArgs) =>
	{
		try
		{
			throw new Exception();
		}
		catch
		{
		}
	};

	try 
	{
		throw new Exception();
	}
	catch
	{
	}
}

This is important to remember if we use any third party libraries, such as a logging library like Log4Net, to log exceptions within the event handler. These third party libraries may throw an exception internally, which will cause the FirstChanceException event to be raised recursively. Even without the use of third party libraries, any code may unexpectedly thrown an exception, which will cause the event to be raised recursively and cause a stack overflow. The MSDN documentation mentions this fact:

You must handle all exceptions that occur in the event handler for the FirstChanceException event. Otherwise, FirstChanceException is raised recursively. This could result in a stack overflow and termination of the application. We recommend that you implement event handlers for this event as constrained execution regions (CERs), to keep infrastructure-related exceptions such as out-of-memory or stack overflow from affecting the virtual machine while the exception notification is being processed.

Unfortunately, the documentation doesn’t provide any code samples. I haven’t been able to figure a way to prevent stack overflows without resorting to a somewhat non-elegant solution. What we can do is check to see if the event handler is found multiple times in the current stack trace. If it is, we can immediately return to prevent the event from being raised again.

static void Main(string[] args)
{
	AppDomain.CurrentDomain.FirstChanceException += (sender, eventArgs) =>
	{
		StackFrame[] frames = new StackTrace(1).GetFrames();
		MethodBase currentMethod = MethodBase.GetCurrentMethod();

		if (frames != null && frames.Any(x => x.GetMethod() == currentMethod))
			return;

		throw new Exception();
	};

	throw new Exception();
}

Instantiating StackTrace may throw an ArgumentOutOfRangeException if the parameter is negative, which is not what we’re doing here. The GetFrames() method may return null, so the if condition needs to check for null. The GetCurrentMethod() method may throw a TargetException if the method was invoked with a late-binding mechanism, which is not what we’re doing here.

The code above should be relatively safe and should prevent a stack overflow if an exception is thrown within the event handler.

“DateTime.Now” in unit tests

May 9, 2012 Leave a comment

Inspired by Ayende’s post about dealing with time in tests, I started using his implementation of SystemTime.Now().

public static class SystemTime
{
    public static Func<DateTime> Now = () => DateTime.Now;
}

We may use SystemTime.Now() anywhere in our code instead of DateTime.Now. This will allow us to control time in a deterministic fashion in order to keep our tests consistent. However, one of the downsides is that we have to remember to reset the time after each test.

[TestMethod]
public void DemoTest()
{
    SystemTime.Now = () => new DateTime(1970, 1, 1);
            
    // Test code...

    SystemTime.Now = () => DateTime.Now;
}

We can ease the pain by implementing this as part of the tear down process that runs after each test. I think that’s an acceptable solution, but I still prefer all my test code to be as close together as possible. The tear down process may also run for tests that don’t deal with SystemTime.Now(), so that’s extra overhead for nothing.

Instead, I decided to add a few additions to SystemTime:

public class SystemTime : IDisposable
{
    private static Func<DateTime> now = () => DateTime.Now;

    public static DateTime Now
    {
        get { return now(); }
    }

    private SystemTime()
    {
    }

    public static SystemTime Context(DateTime dateTime)
    {
        now = () => dateTime;
        return new SystemTime();
    }

    public void Dispose()
    {
        now = () => DateTime.Now;
    }
}

I changed the Now property to type DateTime instead of Func<DateTime> so that it more closely resembles DateTime.Now. Implementing IDisposable gives us an easy way to reset SystemTime.Now.

[TestMethod]
public void DemoTest()
{
    using (SystemTime.Context(new DateTime(1970, 1, 1)))
    {
        // Test code...
    }
}

To demonstrate, we can run this code:

Console.WriteLine(SystemTime.Now);

using (SystemTime.Context(new DateTime(1970, 1, 1)))
{
    Console.WriteLine(SystemTime.Now);
}

Console.WriteLine(SystemTime.Now);

The output is:

5/9/2012 2:21:08 AM
1/1/1970 12:00:00 AM
5/9/2012 2:21:08 AM

ASP.NET MVC CDN UrlHelper

May 6, 2012 Leave a comment

We’re starting to move static files off our production web server to a content delivery network (CDN). Most of our existing views link to static resources using the Url.Content() helper.

<link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="@Url.Content("~/Scripts/jquery.js")"></script>

While in development, I would like the resources to point to the local versions. In production, the resources should point to our CDN. I also want the ability to switch to the local versions if there is a problem with our CDN.

I’ve added two AppSettings keys to the web.config:

<add key="CDN.Enabled" value="true" />
<add key="CDN.Address" value="http://cdn.example.com/" />

If we need to switch to local versions, we can flip CDN.Enabled to false. Instead of using the default Url.Content() helper, we’ll update the views to use our own Url.ContentFromCdn() helper.

<link href="@Url.ContentFromCdn("~/Content/Site.css")" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="@Url.ContentFromCdn("~/Scripts/jquery.js")"></script>

Here is the code for the helper:

public static class UrlHelpers
{
    public static string ContentFromCdn(this UrlHelper helper, string contentPath)
    {
        bool cdnEnabled;

        Boolean.TryParse(
            ConfigurationManager.AppSettings["CDN.Enabled"],
            out cdnEnabled);

        if (!cdnEnabled)
            return helper.Content(contentPath);
            
        var baseUri = new Uri(ConfigurationManager.AppSettings["CDN.Address"]);
        var content = VirtualPathUtility.ToAbsolute(contentPath);

        return new Uri(baseUri, content).AbsoluteUri;
    }
}

The helper will fall back to the default Url.Content() helper if the CDN.Enabled setting evaluates to false. If we need to use Google’s CDN (or any other public CDN), we can use a dictionary to look for specific filenames and return a specific address.

public static class UrlHelpers
{
    private static Dictionary<string, string> cdn = 
        new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
        {
            { "jquery.js", "https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.js" },
            { "jquery-ui.js", "https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.18/jquery-ui.js" }
        };

    public static string ContentFromCdn(this UrlHelper helper, string contentPath)
    {
        bool cdnEnabled;

        Boolean.TryParse(
            ConfigurationManager.AppSettings["CDN.Enabled"],
            out cdnEnabled);

        // Use default Url.Content() helper.
        if (!cdnEnabled)
            return helper.Content(contentPath);

        var fileName = VirtualPathUtility.GetFileName(contentPath);

        // Use public CDN address for this file.
        if (cdn.ContainsKey(fileName))
            return cdn[fileName];
            
        var baseUri = new Uri(ConfigurationManager.AppSettings["CDN.Address"]);
        var content = VirtualPathUtility.ToAbsolute(contentPath);

        return new Uri(baseUri, content).AbsoluteUri;
    }
}

Static fields and the “BeforeFieldInit” flag

May 6, 2012 Leave a comment

While upgrading a legacy WinForm application from .NET 2.0 to .NET 4.0, I noticed some slightly different behavior. I’m working with a class that has a private static field and a few static methods.

public class Demo
{
	private static Expensive expensive = new Expensive();

	public static void Start() 
	{
	}

	public static void UseExpensive()
	{
		expensive.DoSomething();
	}
}

internal class Expensive
{
	public Expensive()
	{
		// Expensive operation
	}

	public void DoSomething()
	{
	}
}

The Demo class uses field initialization to create an instance of the Expensive class. The Start method does not use any of the static fields.

The WinForm application calls Demo.Start() in the constructor and Demo.UseExpensive() in a button event.

public partial class SomeForm : Form
{
	public SomeForm()
	{
		InitializeComponent();

		Demo.Start();
	}

	private void button_Click(object sender, EventArgs e)
	{
		Demo.UseExpensive();
	}
}

In .NET 2.0, the constructor of the Expensive class would execute on application start-up. In .NET 4.0 however, the constructor of the Expensive class would not execute until the button event was fired. Since the Expensive class is costly to create due to various operations in the constructor, the button event in .NET 4.0 was noticeably slower on the first click.

The reason is due to how .NET initializes types that contain static fields and/or a static constructor. If a type does not contain a static constructor, it will be marked with the BeforeFieldInit flag.

Using ILSpy to decompile into IL, we can see the current class marked with BeforeFieldInit:

If we include a static constructor (even if it’s empty), we’ll see that the class is no longer marked with BeforeFieldInit:

When marked with BeforeFieldInit in .NET 2.0, static field initialization may occur at any time before a static field is used. This means that static field initialization may occur even if a static field is never used. When marked with BeforeFieldInit in .NET 4.0, static field initialization only occurs before a static field is used. To demonstrate, we can use a console application to see when events occur.

class Program
{
	static void Main(string[] args)
	{
		Console.WriteLine("Started.");
		Demo.Start();
		Console.WriteLine("End.");
	}
}

public class Demo
{
	private static ExpensiveClass expensive = new ExpensiveClass();

	public static void Start()
	{
		Console.WriteLine("In Start method.");
	}

	public static void UseExpensive()
	{
		Console.WriteLine("In UseExpensive method.");
		expensive.DoSomething();
	}
}

internal class ExpensiveClass
{
	public ExpensiveClass()
	{
		Console.WriteLine("In ExpensiveClass constructor.");
	}

	public void DoSomething()
	{
	}
}

The console application is calling Demo.Start() in the Main method, which does not reference any static fields. The output in .NET 2.0 is:

In ExpensiveClass constructor.
Started.
In Start method.
End.

The output in .NET 4.0 is:

Started.
In Start method.
End.

Although the Demo.Start() method never references any static fields, static field initialization occurs anyway in .NET 2.0.

We can force static field initialization to occur in .NET 4.0 by adding a call to Demo.UseExpensive(), which does reference a static field.

static void Main(string[] args)
{
	Console.WriteLine("Started.");
	Demo.Start();
	Demo.UseExpensive();
	Console.WriteLine("End.");
}

The output in .NET 4.0 is:

Started.
In Start method.
In ExpensiveClass constructor.
In UseExpensive method.
End.

As you can see, static field initialization does not occur in .NET 4.0 until a static field is first referenced.

If we update the Demo class and add an empty static constructor, the class will no longer be marked with BeforeFieldInit. If a type isn’t marked with BeforeFieldInit, static field initialization will occur before any class member is used.

class Program
{
	static void Main(string[] args)
	{
		Console.WriteLine("Started.");
		Demo.Start();
		Console.WriteLine("End.");
	}
}

public class Demo
{
	public static ExpensiveClass expensive = new ExpensiveClass();

	static Demo()
	{
	}

	public static void Start()
	{
		Console.WriteLine("In Start method.");
	}

	public static void UseExpensive()
	{
		Console.WriteLine("In UseExpensive method.");
		expensive.DoSomething();
	}
}

The output for .NET 2.0 and .NET 4.0 will be identical:

Started.
In ExpensiveClass constructor.
In Start method.
End.

WCF clients and IDisposable

May 1, 2012 Leave a comment

There are numerous articles detailing the “broken” IDisposable implementation for WCF clients. Just to name a few:

To summarize, the Close() method will be called when the WCF client is disposed. However, if we try to dispose the client while it’s in a faulted state, an exception will be thrown.

The extension method provided in the CodeProject article allows you do something like this:

new MyTestClient().Using(x => x.DoSomething());

The Using() extension method will automatically close or abort the client once finished. However, I do not like this extension method. Without any explanation, a developer may mistakenly reuse the client:

var client = new MyTestClient();
client.Using(x => x.DoSomething());
client.Using(x => x.DoSomething());  // Connection is already closed.

Instead, I use this class:

public static class Client
{
    public static void Use<TClient>(Action<TClient> action)
        where TClient : ICommunicationObject, new()
    {
        var client = new TClient();

        try
        {
            action(client);
            client.Close();
        }
        catch (Exception)
        {
            client.Abort();
            throw;
        }
    }
}

… and the usage:

Client.Use<MyTestClient>(x => x.DoSomething());

One problem with the class above is that if we needed to instantiate the client using one of the overloaded constructors, we couldn’t due to the new() constraint. Instead, we can use this class:

public class Client<TClient>
    where TClient : ICommunicationObject
{
    private readonly TClient client;

    private Client(TClient client)
    {
        this.client = client;
    }

    public static Client<TClient> Instantiate(Func<TClient> action)
    {
        return new Client<TClient>(action());
    }

    public void Use(Action<TClient> action)
    {
        try
        {
            action(client);
            client.Close();
        }
        catch (Exception)
        {
            client.Abort();
            throw;
        }
    }
}

… and the usage:

Client<MyTestClient>
    .Instantiate(() => new MyTestClient("extra param"))
    .Use(x => x.DoSomething());

Postback and hiding fields

May 1, 2012 Leave a comment

I recently stumbled across some ASP.NET code that looks similar to this:

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        if (!HasPermissions())
            HideSensitiveFields();
    }
}

The code here checks if this is a normal page load and not a postback. If this is the initial page load, it’ll check if the user may see sensitive (administrative) fields and hides them if the user does not have the appropriate permissions.

The problem is that it assumes all initial page loads will enter the !IsPostBack conditional block. Postback can be faked by passing in a few select query strings, such as __EVENTTARGET.

This problem can be solved using event validation, encrypted viewstate, and other better coding practices, but that’s a different subject and I won’t dive into those in this post.

http://localhost:8080/Default.aspx?__eventtarget=

By default, ASP.NET doesn’t check the HTTP verb, so we can pass a few select query string parameters and essentially spoof a postback. The URL above would bypass the !IsPostBack conditional block, allowing access to the sensitive fields.