A quick intro to the HTML Agility Pack

I want a way to extract all the post data out of my blog. To do that I’m building a little application to do that, mostly as an exercise to try out some new technologies. In this post I’m going to show a little of the HTML Agility pack which is the framework I’m using to extract the information out of a blog entry page.

Creating an HtmlDocument

Where in the following code snippet, html is a string containing some HTML

HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(html);

However, the HtmlDocument class also has a Load method that is overloaded and can accept a Stream, TextReader or a string (representing a file path) in order to get the HTML. The one obvious thing that was missing was a version that took a URL although HttpWebResponse does contain a ResponseStream which you could pass in.

Navigating the HTML Document

Once you have loaded in your HTML you will want to navigate it. To do that you need to get hold of HtmlNode that represents the document as a whole:

HtmlNode docNode = doc.DocumentNode;

The docNode will then give you all the bits and pieces you need to navigate around the HTML. If you are also ready used to using the LINQ XML classes introduced in .NET 3.5 then you shouldn’t have too much trouble finding your way around here.

For example, here is a snippet of code that gets all the URLs out of the anchor tags:

var linkUrls = docNode.SelectNodes("//a[@href]")
     .Select(node => node.Attributes["href"].Value);

The linkUrls variable is actually an IEnumerable<string> (if you are curious).

One thing that is particularly annoying

There is one thing that I find particularly annoying however. SelectNodes returns an HtmlNodeCollection, however, if the xpath in the SelectNodes method call results in no nodes being found then it returns a null instead of an empty collection. For me, it is perfectly valid to get an empty collection if the query returned no results. Because of this, I can’t simply write code like the section above. I actually have to check for null before continuing. That means the code in the previous section actually looks like this:

HtmlNodeCollection nodes = docNode.SelectNodes("//a[@href]");
if (nodes != null)
{
    var linkUrls = nodes.Select(node => node.Attributes["href"].Value);
    // And what ever else we were doing.
}

What next?

Well, as you can see the functionality is actually fairly easy to follow. I was initially dismayed at the lack of apparent documentation for it until I realised that the folks that have built the framework have done a great job of ensuring that it works very similarly to libraries already in the .NET framework itself so it is remarkably quick to get used to.

Table names – Singular or Plural

Earlier this morning I tweeted asking for a quick idea of whether to go with singular table names or plural table names. i.e. the difference between having a table called “Country” vs. “Countries”

Here are the very close results:

  • Singular: 8
  • Plural: 6
  • Either: 1

Why Singuar:

  • That’s how the start off life on my ER diagram
  • You don’t need to use a plural name to know a table will hold many of an item.
  • A table consists of rows of items that are singular

Why Plural:

  • It is the only choice unless you are only ever storing one row in each table.
  • because they contain multiple items
  • It contains Users
  • I think of it as a collection rather than a type/class
  • SELECT TOP 1 * FROM Customers

Why either:

  • Either works, so long as it is consistent across the entire db/app

Parallelisation in .NET 4.0 – Part 2 Throwing Exceptions

With more threads running simultaneously in an application there is increasing complexity when it comes to debugging. When exceptions are thrown you usually catch them somewhere and handle them. But what happens if you throw an exception inside a thread?

Naturally, if you can handle the exception within the thread then that makes life much easier. But what if an exception bubbles up and out into code that created the thread?

In the example in my previous post on Parallelisation in .NET 4.0 had the calls to a third party service happening in separate threads. So, what happens if somewhere in the call an exception is raised.

In the service call GetAvailability, I’ve simulated some error conditions to throw exceptions based on the input to illustrate the examples. This is what it looks like:

public HotelAvail GetAvailability(string hotelCode, DateTime startDate, int nights)
{
    // Throw some exceptions depending on the input.
    if (hotelCode == null)
        throw new ArgumentNullException("hotelCode");

    if ((hotelCode.Length > 10) || (hotelCode.Length == 0))
        throw new ArgumentOutOfRangeException(
            "Hotel Codes are 1 to 10 chars in length. Got code which was " +
            hotelCode.Length + " chars.");

    if (hotelCode.StartsWith("Z"))
        throw new AvailabilityException("Hotel code '" + hotelCode +
                                        "' does not exist"); // A custom exception type
    // ... etc. ...
}

The calling code, from the previous example, looks like this:

public IEnumerable<HotelAvail> GetAvailability(IEnumerable<string> codes,
        DateTime startDate, int numNights)
{
        return codes.AsParallel().Select(code =>
            new AvailService().GetAvailability(code, startDate, numNights))
            .ToList();
}

If we provide incorrect input into the service such that it causes exceptions to be raised then Visual Studio responds in the normal way by breaking the debugging session at the point closest to where the exception is thrown.

If we were to wrap the call to the service in a try catch block (as in the following code sample) then we’d except that Visual Studio wouldn’t break the debugging session as there is a handler (the catch block) for the exception.

public IEnumerable<HotelAvail> GetAvailabilityPlinqException(IEnumerable<string> codes,
        DateTime startDate, int numNights)
{
    try
    {
        return codes.AsParallel().Select(code =>
            new AvailService().GetAvailability(code, startDate, numNights))
            .ToList();
    }
    catch (Exception ex)
    {
        // Do stuff to handle the exception.
    }
    return null;
}

Normally, that would be the case, however if the handler is outside the thread that threw the exception, as in the above example, the situation is somewhat different. In this case the Exception Assistant will appear and highlight the exception (or the code nearest the exception if it can’t highlight the throw statement itself*)

AvailabilityException in Exception Assistant

This happens because the exception is not caught within the thread in which it was originally thrown.

The AggregateException

If you just tell the debugger to continue executing the application it will continue, but the code that created the threads will have to handle an AggregateException. This is a special exception class that contains an InnerExceptions (note the plural) property that contains all the exceptions thrown from each of the threads.

AggregateException.InnerExceptions

You can enumerate over each of the inner exceptions to find out what happened in each of the threads.

Be aware, however, that an Aggregate exception can, itself, contain an AggregateException. So simply calling InnerExceptions may yet yield another AggregateException. For example if the hierarchy of exceptions looks like this:

AggregateException Hierarchy

Then the results of iterating over the InnerExceptions will be:

foreach(Exception ex in aggregateException.InnerExceptions)
{
    // ... do stuff ...
}
  • AggregateException
  • ApplicationException

You can flatten the hierarchy into a single AggregateException object that doesn’t contain InnerExceptions with any additional AggregateException objects. To do this call Flatten() on the original AggregateException. This returns a new AggregateException which you can then call InnerExceptions on and not have to worry about any hierarchy.

For example:

foreach(Exception ex in aggregateException.Flatten().InnerExceptions)
{
    // ... do stuff ...
}

Which results in the following exceptions being enumerated by the loop:

  • ApplicationException
  • NullReferenceException
  • ArgumentException
  • DivideByZeroException

But it’s broken, why doesn’t it just stop?

Well, it does. Once a thread has thrown an exception that bubbles up and out then no new tasks are started, so no new threads are created, and no new work gets done. However, remember that there will be other threads running as well and if one breaks, maybe others will break too, or maybe they will complete successfully. We won’t know unless they are allowed to finish what they are doing.

Going back to the room availability example if the input hotel codes contain invalid codes then it will throw an exception that is not caught within the thread. What if a selection of good and bad hotel codes are passed:

1, 2, 3, Z123, 4, 5, 6, 1234567890ABC, 7, 8, 9

Of the above list “Z123” and “1234567890ABC” are both invalid and produce different exceptions. However, when running tests the AggregateException only contains one of the exceptions.

To show what happens, I’ve modified my “service” like this and run it through a console applications. Here’s the full code:

The service class

public class AvailService
{
    // ...

    public HotelAvail GetAvailability(string hotelCode, DateTime startDate, int nights)
    {
        Console.WriteLine("Start @ {0:HH-mm-ss.fff}: {1}", DateTime.Now, hotelCode);

        ValidateInput(hotelCode);

        // ... do stuff to process the request ...

        Console.WriteLine("  End @ {0:HH-mm-ss.fff}: {1}", DateTime.Now, hotelCode);
        return result;
    }

    private void ValidateInput(string hotelCode)
    {
        if (hotelCode == null)
        {
            Console.WriteLine("Error @ {0:HH-mm-ss.fff}: hotelCode is null", DateTime.Now);
            throw new ArgumentNullException("hotelCode");
        }

        if ((hotelCode.Length > 10) || (hotelCode.Length == 0))
        {
            Console.WriteLine("Error @ {0:HH-mm-ss.fff}: hotelCode is {1}", DateTime.Now, hotelCode);
            throw new ArgumentOutOfRangeException(
                "Hotel Codes are 1 to 10 chars in length. Got code which was " +
                hotelCode.Length + " chars.");
        }

        if (hotelCode.StartsWith("Z"))
        {
            Console.WriteLine("Error @ {0:HH-mm-ss.fff}: hotelCode is {1}", DateTime.Now, hotelCode);
            throw new AvailabilityException("Hotel code '" + hotelCode +
                                            "' does not exist");
        }
    }
}

The method on the controller class

public IEnumerable<HotelAvail> GetAvailability(IEnumerable<string> codes,
        DateTime startDate, int numNights)
{
    return codes.AsParallel().Select(code =>
        new AvailService().GetAvailability(code, startDate, numNights))
        .ToList();
}

The Main method on the Program class

static void Main(string[] args)
{
    string[] codes = "1,2,3,Z123,4,5,6,1234567890ABC,,7,8,9".Split(',');
    AvailController ctrl = new AvailController();

    DateTime start = DateTime.Now;
    try
    {
        var result = ctrl.GetAvailability(codes,
            DateTime.Today.AddDays(7.0), 2);
    }
    catch (AggregateException aex)
    {
        Console.WriteLine(aex.Message);

        foreach (Exception ex in aex.InnerExceptions)
            Console.WriteLine(" -- {0}", ex.Message);

    }
    finally
    {
        DateTime end = DateTime.Now;
        Console.WriteLine("Total time in ms: {0}",
                            (end - start).TotalMilliseconds);

    }
}

And the console output is:

Start @ 16-36-36.518: 7
Start @ 16-36-36.518: Z123
Start @ 16-36-36.518: 6
Start @ 16-36-36.518: 1
Error @ 16-36-36.526: hotelCode is Z123
  End @ 16-36-42.438: 1
  End @ 16-36-42.654: 6
  End @ 16-36-42.900: 7
One or more errors occurred.
 -- Hotel code 'Z123' does not exist
Total time in ms: 6400

As you can see only 4 items got started out of an initial input collection of 11 items. The error occurred 8ms after these items started. Those items that did not cause an error were allowed to continue to completion. The result variable in the Main method will never have anything because of the exception so we never get the results of the three items that did succeed.

Naturally, the best course of action is not to let the exception bubble up and out of the thread in which the code is executing.

 

 

* Note, there appears to be a bug in Visual Studio with the Exception Assistant not always highlighting the correct line of code.

Parallelisation in .NET 4.0 – Part 1 looping

In an upcoming project we have a need for using some parallelisation features. There are two aspects to this, one is that we have to make multiple calls out to a web service that can take some time to return and in the meantime we have to get data out of the CMS to match up to the data coming back from the web service.

I’ll be writing a series (just for the irony of it) of posts on these new features in .NET and how we will be implementing them.

The problem

We have a web service that we have to call to get data back to our system. Calls to the web service take in the region of 4 to 7 seconds each to return data to us. The performance of the web service does not degrade significantly if we make multiple calls to it.

The Solution (first attempt)

Since the calls to the web service are not altering state we can safely make those calls in parallel. There is a class called AvailService that calls the web service and gets the results back to us. If you’re interested the web service checks on the availability of rooms in a hotel based on the the hotel code you pass and the stay date range (expressed as a start date and number of nights).

What we could have done in a serial implementation is this:

public IEnumerable<hotelAvail> GetAvailabilitySerial(
    IEnumerable<string> codes, DateTime startDate, int numNights)
{
    List result = new List<hotelAvail>();

    foreach (string code in codes)
    {
        AvailService service = new AvailService();
        HotelAvail singleResult = service.
                GetAvailability(code, startDate, numNights);
        result.Add(singleResult);
    }

    return result;
}

This simply goes around each item and gets the availability of rooms in that hotel for the stay date range. It could be refactored into a LINQ expression, but I’m going to leave it as a fuller loop just to show more clearly what’s going on.

Using Parallel.For

When we change this to a parallel it doesn’t really change much. I’ve changed the list to an array which is set up with the correct size of the result set and each parallel iteration only interacts with one slot in the array.

public IEnumerable<HotelAvail> GetAvailability (
    IList<string> codes, DateTime startDate, int numNights)
{
    HotelAvail[] result = new HotelAvail[codes.Count];

    Parallel.For(0, codes.Count, i =>
        {
            string code = codes[i];
            result[i] = new AvailService().
                GetAvailability(
                    code, startDate, numNights);
        });

    return result;
}

The code in the lambda expression is the part that is parallelised. I’ve had to make some concessions here as well. The IEnumerable of codes is now an IList, this is because I need to be able to access specific indexes into the list in order to align it with the array. That way the there is no accidental overwriting of elements in the result set.

If the ordering of the output is important, (e.g. must be the same order as the input) then this will maintain that ordering. Many of the remaining solutions do not maintain the order.

However, there is a better way to do this that doesn’t involve setting up and maintaining structures in this way and it closer to our serial code.

Using a Parallel.ForEach and a ConcurrentBag

public IEnumerable<HotelAvail> GetAvailabilityConcurrentCollection(
    IEnumerable<string> codes,
    DateTime startDate, int numNights)
{
    ConcurrentBag<HotelAvail> result = new ConcurrentBag();

    Parallel.ForEach(codes, code => result.Add(
        new AvailService().
            GetAvailability(code, startDate, numNights)));

    return result;
}

The content of the Parallel.ForEach here is almost identical to the serial foreach version, except that the code is slightly more terse. However, this time I’m using a ConcurrentBag for the result collection. As the method has always returned an IEnumerable this will not change the return type of the method, meaning that a serial method can be made parallel (assuming other considerations necessary for parallelism are taken into account) fairly easily.

The order of the results may be quite different from the order of the input.

Using PLINQ

Finally, I’ve refactored the code using PLINQ. This example is really quite terse, but if you understand LINQ then it should be very easy to pick up.

public IEnumerable<HotelAvail> GetAvailabilityPlinq(
    IEnumerable<string> codes,
    DateTime startDate, int numNights)
{

    return codes.AsParallel().Select(code =>
        new AvailService().GetAvailability(code, startDate, numNights))
        .ToList();
}

Again, the order of the result may be quite different from the order of the input. If ordering is important to you you can instruct PLINQ to maintain the ordering by using .AsOrdered(). This ensures that the output from the PLINQ expression is in the same order as the input.

e.g.

 

public IEnumerable<HotelAvail> GetAvailabilityPlinq(
    IEnumerable<string> codes,
    DateTime startDate, int numNights)
{

    return codes.AsParallel().AsOrdered().Select(code =>
        new AvailService().GetAvailability(code, startDate, numNights))
        .ToList();
}

The important part to all this is the call to the service, which has remained the same throughout all the samples. It is really just the infrastructure around that call that has changed over these examples.

The results

This table and graph show the results of some tests I ran between the serial and parallel versions. The numbers across the top row and X-axis represent the number of calls to the service. The numbers in the table and Y-Axis represent the time (in seconds) to complete the calls.

 

1 2 3 4 5 6 7 8 9
Serial 5.52 11.22 16.72 22.60 28.59 34.32 40.32 45.67 51.64
Parallel 5.52 6.20 6.35 6.45 11.24 12.35 12.45 12.86 16.66

Parallel vs Serial processing

 

Finally, a warning about using parallelised code from Alex Mackey’s book Introducing .NET 4.0:

“Although parallelization enhancements make writing code to run in parallel much easier, don’t underestimate the increase in complexity that parallelizing an application can bring. Parallelization shares many of the same issues you might have experiences when creating multithreaded applications. You must take care when developing parallel applications to isolate code that can be parallelized.”

Parser Error Message: Ambiguous match found

Symptom

On deploying a newly precompiled web site, the error message as displayed by ASP.NET is as follows:

Server Error in ‘/’ Application.


Parser Error

Description: An error occurred during the parsing of a resource required to service this request. Please review the following specific parse error details and modify your source file appropriately.

Parser Error Message: Ambiguous match found.

Source Error:

Line 1:  <%@ control language="C#" autoeventwireup="true" enableviewstate="false" inherits="WebSiteControls_Offers_TypeFilter, App_Web_typefilter.ascx.bd9a439f" %>

Line 2:
Line 3: <%--

Source File: /WebSiteControls/Offers/TypeFilter.ascx    Line: 1


Version Information: Microsoft .NET Framework Version:2.0.50727.3053; ASP.NET Version:2.0.50727.3053

System Information

This may or may not be relevant, but it reflects my set up at the time I discovered this issue.

  • Web Site project
  • Visual Studio 2008
  • .NET 3.5
  • IIS 6.0

 

Reason

The reason for this is that a control, in this case a Repeater, in the User Control had a similar name as a field on the code behind. The only difference between the two the case. One was called “offerTypes” (in the code behind, an IEnumerable containing entities from the business layer), the other “OfferTypes” (a ASP.NET Repeater control).

Solution

Rename one or other so that the names differ by more that case alone. In my case, I renamed the field referring to the entities to offerTypeInformation.

32bit ASP.NET App on 64bit Windows 7

Recently we all moved to Windows 7 (64bit) on our development machines. With that, we moved also to IIS7.
So that meant that development copies of websites that we are working on have to
be moved to IIS7. This should be simple. Right?

When I attempted to get the first site up and running I got hit by the error “Could not load file or assembly ‘System.Web’ or one of its dependencies. An attempt was made to load a program with an incorrect format.“.
(The full error message is below.)
After searching around I eventually managed to piece together that the reason
was that IIS was trying to run in 64 bit mode and this application was compiled
as a 32 bit application. Okay…. So how do you fix this?

It turns out the fix is rather easy. In the IIS Manager, open up the list of
Application Pools and select the pool for your application. Right-click and
select “Advanced Settings”. From that point you get this dialog:

32-bit application

Just set “Enable 32-bit applications” to “True”, then Okay the dialog. You then
have to recycle the Application Pool for the change to take effect.

 

 

Server Error in ‘/’ Application.


Could not load file or assembly ‘System.Web’ or one of its dependencies. An attempt was made to load a program with an incorrect format.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.BadImageFormatException: Could not load file or assembly ‘System.Web’ or one of its dependencies. An attempt was made to load a program with an incorrect format.

Source Error:

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

Assembly Load Trace: The following information can be helpful to determine why the assembly ‘System.Web’ could not be loaded.


WRN: Assembly binding logging is turned OFF.
To enable assembly bind failure logging, set the registry value [HKLMSoftwareMicrosoftFusion!EnableLog] (DWORD) to 1.
Note: There is some performance penalty associated with assembly bind failure logging.
To turn this feature off, remove the registry value [HKLMSoftwareMicrosoftFusion!EnableLog].

Stack Trace:


[BadImageFormatException: Could not load file or assembly 'System.Web' or one of its dependencies. An attempt was made to load a program with an incorrect format.]
   System.Reflection.Assembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection) +0
   System.Reflection.Assembly.InternalLoad(AssemblyName assemblyRef, Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection) +416
   System.Reflection.Assembly.InternalLoad(String assemblyString, Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection) +166
   System.Reflection.Assembly.Load(String assemblyString) +35
   System.Web.Configuration.CompilationSection.LoadAssemblyHelper(String assemblyName, Boolean starDirective) +190

[ConfigurationErrorsException: Could not load file or assembly 'System.Web' or one of its dependencies. An attempt was made to load a program with an incorrect format.]
   System.Web.Configuration.CompilationSection.LoadAssemblyHelper(String assemblyName, Boolean starDirective) +11207304
   System.Web.Configuration.CompilationSection.LoadAllAssembliesFromAppDomainBinDirectory() +388
   System.Web.Configuration.CompilationSection.LoadAssembly(AssemblyInfo ai) +232
   System.Web.Configuration.AssemblyInfo.get_AssemblyInternal() +48
   System.Web.Compilation.BuildManager.GetReferencedAssemblies(CompilationSection compConfig) +210
   System.Web.Compilation.BuildProvidersCompiler..ctor(VirtualPath configPath, Boolean supportLocalization, String outputAssemblyName) +76
   System.Web.Compilation.CodeDirectoryCompiler.GetCodeDirectoryAssembly(VirtualPath virtualDir, CodeDirectoryType dirType, String assemblyName, StringSet excludedSubdirectories, Boolean isDirectoryAllowed) +11196482
   System.Web.Compilation.BuildManager.CompileCodeDirectory(VirtualPath virtualDir, CodeDirectoryType dirType, String assemblyName, StringSet excludedSubdirectories) +185
   System.Web.Compilation.BuildManager.EnsureTopLevelFilesCompiled() +551

[HttpException (0x80004005): Could not load file or assembly 'System.Web' or one of its dependencies. An attempt was made to load a program with an incorrect format.]
   System.Web.Compilation.BuildManager.ReportTopLevelCompilationException() +76
   System.Web.Compilation.BuildManager.EnsureTopLevelFilesCompiled() +1012
   System.Web.Hosting.HostingEnvironment.Initialize(ApplicationManager appManager, IApplicationHost appHost, IConfigMapPathFactory configMapPathFactory, HostingEnvironmentParameters hostingParameters) +1025

[HttpException (0x80004005): Could not load file or assembly 'System.Web' or one of its dependencies. An attempt was made to load a program with an incorrect format.]
   System.Web.HttpRuntime.FirstRequestInit(HttpContext context) +11301302
   System.Web.HttpRuntime.EnsureFirstRequestInit(HttpContext context) +88
   System.Web.HttpRuntime.ProcessRequestInternal(HttpWorkerRequest wr) +11174792


Version Information: Microsoft .NET Framework Version:2.0.50727.4927; ASP.NET Version:2.0.50727.4927

Type Inference

Type Inference is a neat feature where the C# compiler can work out itself what type a reference to an object is. While this can be used for the developer to be lazy it is most useful when you are dealing with the exceptionally long type names that LINQ expressions can generate. It is also a requirement when dealing with anonymous types, because there simply is no type name that you can use.

For example:

var aString = “ABC”;
Type st = aString.GetType(); // System.String;

var aNumber = 123.45M;
Type nt = aNumber.GetType(); // System.Decimal

var aDate = DateTime.Now;
Type dt = aDate.GetType(); // System.DateTime

In each of the above examples the compiler works out from what is on the right side of the equals sign the type of the reference (or value) on the left hand side.

What is important is that the compiler has something it can work with. In other words, you must assign something.

var aString; // Illegal – Can’t infer type

// Computer says "no":
// Implicitly-typed local variables must be initialized

Also, because the variable is strongly typed from the get-go each time you assign something to it, it must be of the same type.

var aDate = DateTime.Now;
aDate = 123; // Illegal – Can’t change type

// Computer says "no":
// Cannot implicitly convert type 'int' to 'System.DateTime'

Lambda cheat sheet

A while ago I wrote about all the new language features of C# 3.0 and it occurred to me that I’d left out a chunk about Lambdas. With LINQ being such an important part of C#3.0 that seems like a terrible omission, so I’m going to make up for it now.

The easiest way to think about a lambda is that it is a short form of anonymous methods that were introduced in C#2. However, you can also use lambdas to create expression trees (I’ll come to those in more detail in another post, for the moment, I’ll be concentrate on using lambdas for creating anonymous methods).

Basic Structure

A lambda that looks like this

(i) => 123 + i
^^^ ^^ ^^^^^^^
(1) (2)  (3)

is compiled to an anonymous method

delegate (int i) { return 123+i; }
         ^^^^^^^   ^^^^^^^^^^^^^
           (1)          (3)

The first part of the lambda (1), in the brackets, declares the parameters. The brackets are, incidentally, optional if there is only one parameter. The type is inferred so you don’t have to explicitly declare it as you would have to do with an anonymous method. However, if the compiler cannot infer the parameter type then you will have to declare it explicitly:

(int i) => 123 + i

The second part (2) is pronounced “goes to” and does not really have an equivalent with an anonymous method, although you could argue that it is the equivalent of the delegate keyword.

The third part (3) is the expression or statement. In a lambda expression the return is implicit so it does not need to be declared. It can also contain a number of statements enclosed in separated by semi-colon, but in that case it cannot be used to create expression trees and you must explicitly have a return statement if there is something being returned.

delegate void DisplayAdditionDelegate(int i, int j);

DisplayAdditionDelegate add = (i, j) =>
    { Console.WriteLine("{0} + {1} = {2}", i, j, i+j); };
add(2, 5);
// Output is: 2 + 5 = 7

Framework assistance

The .NET Framework provides a number of predefined generic delegate types that can be used with lambdas in order that is is easy to refer to them and pass them around.

Each of these contains a generic list of parameter types and finally the return type, or if there are no parameters just the return type.

The delegates with a return type are defined as:

public delegate TResult Func<TResult>()
public delegate TResult Func<T, TResult>(T arg)
public delegate TResult Func<T1, T2, TResult>(T1 arg1, T2 arg2)
public delegate TResult Func<T1, T2, T3, TResult>(T1 arg1, T2 arg2, T3 arg3)
public delegate TResult Func<T1, T2, T3, T4, TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4)

The delegates without a return type are defined as:

public delegate void Action<T>(T obj)
public delegate void Action<T1, T2>(T arg1, T2 arg2)
public delegate void Action<T1, T2, T3>(T arg1, T2 arg2, T3 arg3)
public delegate void Action<T1, T2, T3, T4>(T arg1, T2 arg2, T3 arg3, T4 arg4)

You can then uses these delegates to represent an appropriate method without having to create a custom delegate type – for most purposes they are quite sufficient.

Outer variables

Outer variables are variables that the lambda can use that are defined in the method that defines the lambda.

int j = 25;
Func<int, int> function = i => 100 + i + j;
j = 75;
int result = function(50);
// result == 225

As you can see in the above example the value of j is not evaluated at the point the lambda is declared, but at the point it is invoked. The lambda is able to keep a reference to j even although it was declared in a different scope. The same is true if the lambda is eventually invoked from a different scope block altogether. For example, if it has been passed out of the method in which it is declared.

The lambda can also change the value of the outer variable. For example:

int j = 6;
Func<int, int> function = i => { j = j * j; return 100 + i + j; };
int result = function(50);
// result == 186
// j == 36

Updated chart of .NET version numbers

Way back when, I published a table detailing the version numbers of the various parts that make up a .NET application: The Tools, the C# language, the Framework itself and the Engine (CLR) that it all runs on. With the latest version about to be released I thought it was time to update that table.

 

Year 2002 2003 2005 2006 2007 2010
Tool VS.NET 2002 VS.NET 2003 VS 2005 VS 2005
+ Extension
VS 2008 VS 2010
Language (C#) v1.0 v1.1 v2.0 v2.0 v3.0 v4.0
Framework v1.0 v1.1 v2.0 v3.0 v3.5 v4.0
Engine (CLR) v1.0 v1.1 v2.0 v2.0 v2.0 v4.0

 

The main new thing is that finally someone has had the good sense to re-sync the version numbers. It all got a bit silly with the release of Visual Studio 2008.

Integrating Exceptioneer with OpenRasta

[NOTE: This post was created using OpenRasta 2.0 RC (rev 429)]

One service I’ve found to be increasingly useful is Exceptioneer by Pixel Programming. As I’m about to start a new project using OpenRasta I wanted to be able to use Exceptioneer with it in order that I can log any exceptions effectively.

For a basic 404 error it was very easy. Just following the instructions on the Exceptioneer site for the ASP.NET integration worked a treat.

However, a little more work was required for when something like a Handler in OpenRasta threw an exception that didn’t get caught. In this case I had to set up an OperationInterceptor in order to catch the exception and send it to Exceptioneer.

Here is the ExceptionInterceptor class:

class ExceptionInterceptor : OperationInterceptor
{
    readonly IDependencyResolver resolver;

    public ExceptionInterceptor(IDependencyResolver resolver)
    {
        this.resolver = resolver;
    }

    public override Func<IEnumerable<OutputMember>> RewriteOperation
        (Func<IEnumerable<OutputMember>> operationBuilder)
    {
        return () =>
        {
            IEnumerable<OutputMember> result = null;
            try
            {
                result = operationBuilder();
            }
            catch (Exception ex)
            {
                Client exceptioneerClient = new Client();
                exceptioneerClient.CurrentException = ex;
                exceptioneerClient.Submit();
                throw;
            }
            return result;
        };
    }
}

Note that you have to include using Exceptioneer.WebClient; at the top of the file.

What this gives us is the ability to log any exception that is left uncaught from the Handler, log it then allow OpenRasta to continue on as it would have normally.

All that remains is to wire this up. In the Configuration class (if you’ve used the Visual Studio 2008 project template, or what ever your IConfigurationSource class is called otherwise) the following is added to the Configure method:

ResourceSpace.Uses.CustomDependency<IOperationInterceptor,
    ExceptionInterceptor>(DependencyLifetime.Transient);

 

Now any time a handler has an uncaught exception, it will be logged and sent off to Exceptioneer.

Further reading: