First(OrDefault) Vs. Single(OrDefault)

There are two mechanisms (each with an …OrDefault variant) in LINQ for getting one item out of an enumeration. They are First and Single. There is a difference between the two and you can produce code that functions incorrectly if the wrong one is used.

So, what’s the main difference? They both sound like they’ll return just one item out from the enumeration. And, indeed, they do.

First will return the first item that it encounters that matches the predicate (if supplied). Whereas Single will return the one and only item that it encounters that matches the predicate (if supplied). If Single encounters a second item that matches the predicate then it throws an exception. If no predicate is supplied, it throws an exception simply if the enumeration has more that one item.

Why would there be two things that do almost the same thing that are so subtly different? First exists so that you can get the first item regardless of how many items there may actually be. Single exists to get you the one and only item. Single is useful when your predicate operates on a primary key. For example:

data.Single(d => d.PrimaryKey == idToMatch)

The …OrDefault variants will return the default value for the type (for reference types that will be null) if there are no matches found. Otherwise, both First and Single throw an exception if no items are encountered.

Lets look at some code.

First

string[] data = new[]{"Zero", "One", "Two", "Three",
    "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten"};
var first = data.First();

In this case, first will contain the value of "Zero".

If a predicate is added to the call to First then we can see what happens if there is no match.

string[] data = new[]{"Zero", "One", "Two", "Three",
    "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten"};
var first = data.First(x => x.Length > 10);

In this case, there are no matches, and an InvalidOperationException is thrown with the message “Sequence contains no matching element”

The same thing will happen if the initial set of data is empty

string[] empty = new string[0];
var first = empty.First();

You can happily supply a predicate that may match more than one item in the enumeration

Single

For example

string[] onlyOneItem = new string[]{"Only item"};
var single = onlyOneItem.Single();

This will return the one and only item that matches.

string[] data = new[]{"Zero", "One", "Two", "Three",
    "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten"};
var single = data.Single();

This will thrown an exception. If result set contains more than one item an InvalidOpertationException will be thrown with a message of “Sequence contains more than one element”

string[] empty = new string[0];
var single = empty.Single();

This will throw exactly the same exception as it’s First counterpart; an InvalidOperationException is thrown with the message “Sequence contains no matching element”

…OrDefault

This is where things get a little bit more interesting. This says that if the result set contains zero items null (for reference types) is returned. In the case of First, the result set can contain zero, one or many items and it won’t throw an exception. In the case of Single only result sets containing zero or one item will return while any more will result in an exception.

So… what about this scenario:

string[] data = new[]{null, "Zero", "One", "Two", "Three",
    "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten"};
var first = data.FirstOrDefault();

The first value of the set is genuinely null. How do you tell the difference between that and the result set being simply empty without throwing an exception?

You could just go back to using the First variant and catching the exception. Or you could (if your result set can be enumerated many times without issue, e.g. the underlying object is an Array or List) use Any to test if the set contains any data in advance. Like this:

string[] data = new[]{null, "Zero", "One", "Two", "Three",
    "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten"};
if (data.Any())
{
    var first = data.FirstOrDefault();
    // Do stuff with the value
}

LINQ query performance

A while ago I was reviewing some code and I came across some code that looked like this

if (corpus.Where(a => a.SomeProperty == someValue).Count() > 0)
{
    // Do Stuff
}

And it got me thinking that it may not be the best way to do this. What is really being asked here is: “Are there any items in the enumerable?” The count is not actually important in this situation. I considered that it would probably be more efficient to write:

if (corpus.Where(a => a.SomeProperty == someValue).Any())
{
    // Do stuff
}

Then I read somewhere (unfortunately, I didn’t note the URL) that for certain situations the .Any() extension method on IEnumerable<T> can be inefficient in certain scenarios. For instance, if concrete type is actually a List<T> which maintains its own Count. In that instance the cost of setting up the Enumerator and calling MoveNext() to determine the existence of at least one element would be more expensive an operation than calling Count on the List<T>.

I was curious about that so I set about working out the relative performance characteristics of a number of the LINQ extension methods. I should note that these were all on LINQ to Objects out of the box so don’t measure how these methods would perform relatively for things like, say, LINQ to SQL.

I tested various scenarios, some where the IEnumerable<T> is a lightweight generator of elements, in this case an Enumerable.Range(…), in other cases I used a List<T> either by a concrete reference or by an reference to the IEnumerable<T> interface.

All timings in this post relate to my desktop machine which is running Windows 7 64bit with 8Gb RAM and an AMD Phenom II X4 955 running at 1.6GHz (which for some unknown reason it won’t run at the full 3.2GHz)

Counting elements

In the first set of tests I counted the number of elements. For the cases where I called the Count property directly on the List<T> and used the Count() extension method on IEnumerable<T> where the concrete type was the List<T> the result was returned in O(1). The LINQ method was 24 times slower.

Where the IEnumerable<T> did not also implement the ICollection<T> interface (as in the case where the values were being generated by Enumerable.Range(…) method) the Count() extension method took O(n) time to return the answer.

The graph above shows the number of Ticks (vertical axis) taken to complete the counting task with n (horizontal axis) elements. A tick is roughly 1/1600th of a millisecond. So for 2000000 elements it took 72.5ms to count them.

Compare that for instances where the Count property was called directly (0.00413 Ticks or 0.00258µs [millionths of a second]) or where the Count() method was called on something that could be cast to an ICollection or ICollection<T> (0.0989 Ticks or 0.0618µs)

So far it looks good for cases where the underlying type implements the ICollection<T> or ICollection interface. However remember as soon as you start filtering the data (e.g. with a Where() method call) then you are returning an IEnumerable<T> which then operates in O(n) time. Also remember that the Where() clause will add some overhead as it has to process the filter as well.

Any elements

It should be no surprise that using our test set of a List<T> and an Enumerable.Range(…) the Any() method runs in O(1) time. Both took similar amounts of time, the former taking 0.278 Ticks (0.174µs) per call, and the latter taking 0.296 Ticks (0.185µs) per call. I suspect that time on the latter is more due to the the small amount of additional time taken to generate additional elements as the enumerator progresses.

However, if you have a reference to something that already implements ICollection<T> which defines a Count property, such as a List<T>, you may find it is faster to perform (corpus.Count>0). I found that for the List<T> I’d created for the test runs it was only marginally slower than the raw call to Count taking 0.00607 ticks (0.00379µs) per call.

Any elements with filter

If you have a filter (a Where clause) then Any may take longer that O(1). It will take as long as it takes to find anything that matches the filter or O(n) if nothing matches the filter.

I ran three tests, one where the filtered condition was met on the first element, one where the condition was met in the middle of the set and one where the condition was not met until the last element.

Summary

If you have a concrete type the performance is better when using the Count property both for cases when you need to know the number of elements in the corpus or when you need to know if there any any elements at all.

If you simply need to know if there are any elements at all in the corpus then the use of Any() works out better than using the LINQ extension method Count() as Count() must traverse the entire corpus (unless it derives from ICollection<T> whereas Any() will short circuit at the first available opportunity.

Opting out of Google Instant Browsing

I recently wrote about a new feature of Google Chrome called Instant Browsing. You can turn it on or off Basic tab of the  Options page in Chrome.

If you are a web site owner/administrator and are concerned about the impact it might have on your web server to have a deluge of requests going to your server that the end user is probably not really interested in, or having a number of requests going to your server that result in a 404 resource not found because the half formed URL in the “omnibox” does not actually resolve to a real page then you can opt out.

For folks running ASP.NET (both WebForms and MVC) I’ve created a simple HTTP Module that will opt your site out if it encounters requests from Chromes’ Instant Browsing.

You can download the Module here: Instant Browsing HTTP Module V1. And to activate it in your application you need to add the DLL file as a reference to your application and then add the bolded line to your web.config.

<configuration>
 <system.web>
  <httpModules>
   <add name="InstantBrowsingOptOut" type="InstantBrowsing.InstantBrowsingOptOut, InstantBrowsing"/>
  </httpModules>
 </system.web>
</configuration>

 

The Code

If you prefer, you can add the following source to your application and compile it yourself.

using System;
using System.Collections.Specialized;
using System.Web;

namespace InstantBrowsing
{
    public class InstantBrowsingOptOut : IHttpModule
    {
        public void Dispose()
        {
            // Nothing to dispose. Required by IHttpModule
        }

        public void Init(HttpApplication context)
        {
            context.BeginRequest += new EventHandler(BeginRequest);
        }

        void BeginRequest(object sender, EventArgs e)
        {
            HttpApplication application = (HttpApplication)sender;

            string headerValue = GetPurposeHeaderValue(application.Request);
            if (HeaderValueDoesntExist(headerValue))
                return;

            if (PreviewMode(headerValue))
                Issue403Forbidden(application.Response);
        }

        private bool PreviewMode(string value)
        {
            return value.ToLowerInvariant().Contains("preview");
        }

        private bool HeaderValueDoesntExist(string value)
        {
            return string.IsNullOrEmpty(value);
        }

        private string GetPurposeHeaderValue(HttpRequest request)
        {
            NameValueCollection headers = request.Headers;
            return headers["X-Purpose"];
        }

        private void Issue403Forbidden(HttpResponse response)
        {
            response.Clear();
            response.StatusCode = 403;
            response.End();
        }
    }
}

And to activate it in your application you need to add the bolded line to your web.config.

<configuration>
 <system.web>
  <httpModules>
   <add name="InstantBrowsingOptOut" type="InstantBrowsing.InstantBrowsingOptOut, InstantBrowsing"/>
  </httpModules>
 </system.web>
</configuration>

Note that the second “InstantBrowsing” in the type attribute is the assembly, so if you’ve put it in an assembly with a different name you’ll need to change the type attribute to reflect that.

Tip of the day: Splitting a string when encountering whitespace

In .NET the string class has a Split method that splits the string at the separator character(s) that you specify. However, if you want to split the string at any instance of whitespace you don’t have to create a Split call that enumerates all those different types of whitespace… and there are actually quite a lot! Instead you can just call Split without any parameters and it will split at whitespace regardless of the type.

For example, the following program, in which I hope I’ve managed to use all the different types of whitespace in Unicode, will produce the output below:

static void Main(string[] args)
{
  string source = "Anu0020inspiredrcalligrapherncanu1680createu180epagesu2000ofu2001"+
    "beautytusingu2002sticku2003ink,u2004quill,u2005brush,u2006pick-axe,u2007buzzu2008"+
    "saw,u2009oru200aevenu202fstrawberryu205fjam."+
    Environment.NewLine+
    "Theu3000quicku2028brownu2029foxu0009jumpsu000aoveru000btheu000clazyu000ddog."+
    Environment.NewLine+
    "Whitespaceu0085Foru00a0the win!";

  string[] words = source.Split();

  foreach(string word in words)
  {
    Console.WriteLine(word);
  }
}

Produces this output:

An
inspired
calligrapher
can
create
pages
of
beauty
using
stick
ink,
quill,
brush,
pick-axe,
buzz
saw,
or
even
strawberry
jam.

The
quick
brown
fox
jumps
over
the
lazy
dog.

Whitespace
For
the
win!

Building messages in parallel

I recently saw some code where the developer was attempting to build up messages inside tasks that were being reported outside of the task.

In a sequential system it is easy enough to do this. You have various options available to you, such as

  • message += …;
  • StringBuilder
  • Streams

However, in a parallel system these all fall down because you lose control over the sequencing. You can regain some control by using appropriate locks but then you add in bottlenecks around the synchronisation points which is something you want to minimise in a parallel system.

I’ll show you what I mean. Each example below is attempting to build up a large message containing messages from smaller subroutines. For the moment, let’s assume that the exact order of the individual messages are not important. It may be a series of log entries, or a list of errors to correct. The only important thing is that each individual message is not garbled in anyway. [Skip the code]

The example message is actually just a set of letters and numbers. In the final message each letter must appear 10 times and each number 26 times. Once the tasks have finished, the final messages are examined to see what happened.

Sequential Reference code

Here is the code:

class Program
{
    static void Main(string[] args)
    {
        string result = SequentialReference();

        ShowResult(result);

        Console.WriteLine("Program finished");
        Console.ReadLine();
    }

    private static string SequentialReference()
    {
        string result = string.Empty;

        for(int i=0; i<10; i++)
        {
            for(char c='A'; c<='Z'; c++)
            {
                result += string.Format("{0}{1}", i, c);
            }
            result += Environment.NewLine;
        }

        return result;
    }

    private static void ShowResult(string message)
    {
        // Code to display the message and the
        // results of the tests
    }
}

The code generates the messages, then outputs the results. For the reference sequential code (which is what we want all the results to look like) we get:

0A0B0C0D0E0F0G0H0I0J0K0L0M0N0O0P0Q0R0S0T0U0V0W0X0Y0Z
1A1B1C1D1E1F1G1H1I1J1K1L1M1N1O1P1Q1R1S1T1U1V1W1X1Y1Z
2A2B2C2D2E2F2G2H2I2J2K2L2M2N2O2P2Q2R2S2T2U2V2W2X2Y2Z
3A3B3C3D3E3F3G3H3I3J3K3L3M3N3O3P3Q3R3S3T3U3V3W3X3Y3Z
4A4B4C4D4E4F4G4H4I4J4K4L4M4N4O4P4Q4R4S4T4U4V4W4X4Y4Z
5A5B5C5D5E5F5G5H5I5J5K5L5M5N5O5P5Q5R5S5T5U5V5W5X5Y5Z
6A6B6C6D6E6F6G6H6I6J6K6L6M6N6O6P6Q6R6S6T6U6V6W6X6Y6Z
7A7B7C7D7E7F7G7H7I7J7K7L7M7N7O7P7Q7R7S7T7U7V7W7X7Y7Z
8A8B8C8D8E8F8G8H8I8J8K8L8M8N8O8P8Q8R8S8T8U8V8W8X8Y8Z
9A9B9C9D9E9F9G9H9I9J9K9L9M9N9O9P9Q9R9S9T9U9V9W9X9Y9Z

Does the result contain all the necessary parts?
10 of each letter; 26 of each number
0: 26 occurrences: Pass
1: 26 occurrences: Pass
2: 26 occurrences: Pass
3: 26 occurrences: Pass
4: 26 occurrences: Pass
5: 26 occurrences: Pass
6: 26 occurrences: Pass
7: 26 occurrences: Pass
8: 26 occurrences: Pass
9: 26 occurrences: Pass
A: 10 occurrences: Pass
B: 10 occurrences: Pass
C: 10 occurrences: Pass
D: 10 occurrences: Pass
E: 10 occurrences: Pass
F: 10 occurrences: Pass
G: 10 occurrences: Pass
H: 10 occurrences: Pass
I: 10 occurrences: Pass
J: 10 occurrences: Pass
K: 10 occurrences: Pass
L: 10 occurrences: Pass
M: 10 occurrences: Pass
N: 10 occurrences: Pass
O: 10 occurrences: Pass
P: 10 occurrences: Pass
Q: 10 occurrences: Pass
R: 10 occurrences: Pass
S: 10 occurrences: Pass
T: 10 occurrences: Pass
U: 10 occurrences: Pass
V: 10 occurrences: Pass
W: 10 occurrences: Pass
X: 10 occurrences: Pass
Y: 10 occurrences: Pass
Z: 10 occurrences: Pass
Does the result contain correctly sequenced individual messages?
Each sequence 52 chars; 0A0B0C... 1A1B1C.... etc.
Message 0: PASS - 52 char; PASS - Message content as expected
Message 1: PASS - 52 char; PASS - Message content as expected
Message 2: PASS - 52 char; PASS - Message content as expected
Message 3: PASS - 52 char; PASS - Message content as expected
Message 4: PASS - 52 char; PASS - Message content as expected
Message 5: PASS - 52 char; PASS - Message content as expected
Message 6: PASS - 52 char; PASS - Message content as expected
Message 7: PASS - 52 char; PASS - Message content as expected
Message 8: PASS - 52 char; PASS - Message content as expected
Message 9: PASS - 52 char; PASS - Message content as expected
Program finished

String Concatenation in parallel

The first bad parallel example is this one, where the message is built up using string concatenation.  The code is almost identical to the sequential example, except that the for loop is now a Parallel.For and I’ve injected a Sleep to simulate performing other work (such as getting the data necessary to build the messages).

class Program
{
    static void Main(string[] args)
    {
        string message = StringConcat();

        ShowResult(message);

        Console.WriteLine("Program finished");
        Console.ReadLine();
    }

    private static string StringConcat()
    {
        string result = string.Empty;

        Parallel.For(0, 10,
                        (int i) =>
                            {
                                for (char c = 'A'; c <= 'Z'; c++)
                                {
                                    result += string.Format("{0}{1}",i, c);
                                    Thread.Sleep(15);
                                }
                                result += Environment.NewLine;
                            });

        return result;
    }
}

And the results are starkly different:

0A2A4A6A8A2B0B6B4B8B2C0C6C8C2D0D6D4D8D2E0E4E8E2F0F4F6F8F2G0G4G6G8G2H0H4H8H2I0I4I
8I2J0J6J4J8J2K0K4K8K2L0L6L4L8L2M0M6M8M2N0N4N8N2O0O4O8O2P0P6P4P8P2Q0Q4Q8Q2R0R6R4R
8R2S0S6S4S8S2T0T4T8T2U0U4U8U2V0V6V4V8V2W0W6W8W2X0X6X8X2Y0Y4Y8Y2Z0Z4Z6Z8Z
3A
1A
5A
7A
9A3B1B5B7B9B3C1C7C9C3D1D5D9D3E1E7E9E3F1F5F7F9F3G1G5G9G3H1H5H9H3I1I7I5I9I3J1J7J9J
3K1K5K7K9K3L1L7L5L9L3M1M5M9M3N1N5N7N9N3O1O5O7O9O3P1P7P9P3Q1Q7Q5Q9Q3R1R7R5R9R1S3S
7S5S9S3T1T5T7T9T3U7U5U9U1V5V9V3W7W9W1X3X7X5X9X3Y1Y7Y5Y9Y1Z7Z9Z

Does the result contain all the necessary parts?
10 of each letter; 26 of each number
0: 26 occurrences: Pass
1: 24 occurrences: Fail
2: 26 occurrences: Pass
3: 24 occurrences: Fail
4: 22 occurrences: Fail
5: 20 occurrences: Fail
6: 16 occurrences: Fail
7: 21 occurrences: Fail
8: 26 occurrences: Pass
9: 26 occurrences: Pass
A: 10 occurrences: Pass
B: 10 occurrences: Pass
C: 8 occurrences: Fail
D: 9 occurrences: Fail
E: 8 occurrences: Fail
F: 10 occurrences: Pass
G: 9 occurrences: Fail
H: 8 occurrences: Fail
I: 9 occurrences: Fail
J: 9 occurrences: Fail
K: 9 occurrences: Fail
L: 10 occurrences: Pass
M: 8 occurrences: Fail
N: 9 occurrences: Fail
O: 9 occurrences: Fail
P: 9 occurrences: Fail
Q: 9 occurrences: Fail
R: 10 occurrences: Pass
S: 10 occurrences: Pass
T: 9 occurrences: Fail
U: 8 occurrences: Fail
V: 8 occurrences: Fail
W: 7 occurrences: Fail
X: 9 occurrences: Fail
Y: 9 occurrences: Fail
Z: 8 occurrences: Fail
Does the result contain correctly sequenced individual messages?
Each sequence 52 chars; 0A0B0C... 1A1B1C.... etc.
Message 0: FAIL - Expected 52 / Got 232 characters
Message 1: FAIL - Expected 52 / Got 2 characters
Message 2: FAIL - Expected 52 / Got 2 characters
Message 3: FAIL - Expected 52 / Got 2 characters
Message 4: FAIL - Expected 52 / Got 2 characters
Message 5: FAIL - Expected 52 / Got 222 characters
Program finished

As you can see, some of it works out… Most of it is a mess!

So what happened?

The string that will contain the result was created outside of the parallel tasks. Inside the tasks the result was updated without any synchronisation structure in place. That means that all the tasks could update the intermediate stages of the result and in the process overwrite each others changes, insert items out of sequence and so on.

I’ve written about some of ways that the Parallel Extensions can help with synchronisation of data across parallel tasks before (e.g. the ConcurrentDictionary being used to help with the aggregation of grouped counts) so perhaps here is an example of where another of the concurrent collections may come in handy. A ConcurrentBag could be used to hold each of the individual completed messages.

A ConcurrentBag is an unordered collection of objects that you can access across multiple threads in a safe way. You can add the same object to the bag as many times as you like. As it is unordered you cannot rely on the objects being retrieved in any particular sequence.

The code that builds the messages now looks like this:

private static string ConcurrentBagExample()
{
    ConcurrentBag<string> bag = new ConcurrentBag<string>();

    Parallel.For(0, 10,
                    (i) =>
                    {
                        string result = string.Empty;
                        for (char c = 'A'; c <= 'Z'; c++)
                        {
                            result += string.Format("{0}{1}", i, c);
                            Thread.Sleep(15);
                        }
                        bag.Add(result);
                    });

    return string.Join(Environment.NewLine, bag);
}

What has changed is that the building of the string has moved inside the task. This means that the task can only build the string for itself. Once it is done the string is added to the ConcurrentBag. The final string is built outside the parallel tasks. At the end of the method a simple string.Join() is used to pull all the data that’s been built up in the ConcurrentBag.

And now the messages are formed correctly. The only difference between the output of this program and that of the sequential reference program [see above] is the ordering of the individual messages:

1A1B1C1D1E1F1G1H1I1J1K1L1M1N1O1P1Q1R1S1T1U1V1W1X1Y1Z
0A0B0C0D0E0F0G0H0I0J0K0L0M0N0O0P0Q0R0S0T0U0V0W0X0Y0Z
3A3B3C3D3E3F3G3H3I3J3K3L3M3N3O3P3Q3R3S3T3U3V3W3X3Y3Z
2A2B2C2D2E2F2G2H2I2J2K2L2M2N2O2P2Q2R2S2T2U2V2W2X2Y2Z
5A5B5C5D5E5F5G5H5I5J5K5L5M5N5O5P5Q5R5S5T5U5V5W5X5Y5Z
4A4B4C4D4E4F4G4H4I4J4K4L4M4N4O4P4Q4R4S4T4U4V4W4X4Y4Z
7A7B7C7D7E7F7G7H7I7J7K7L7M7N7O7P7Q7R7S7T7U7V7W7X7Y7Z
6A6B6C6D6E6F6G6H6I6J6K6L6M6N6O6P6Q6R6S6T6U6V6W6X6Y6Z
9A9B9C9D9E9F9G9H9I9J9K9L9M9N9O9P9Q9R9S9T9U9V9W9X9Y9Z
8A8B8C8D8E8F8G8H8I8J8K8L8M8N8O8P8Q8R8S8T8U8V8W8X8Y8Z

Parallel Tasks and the HttpContext

A few days ago I spotted a question on StackOverflow by someone trying to use a parallel loop in an ASP.NET application. It may have been an ASP.NET MVC application (I don’t recall) but the issue is the same.

This person had some code in a parallel task that was using the HttpContext object. I would be hesitant to use that object in the first instance as I don’t know how thread safe it is. I suspect that since it holds a lot of information about the state of a request/response that it would be quite dangerous to access an instance in many threads.

His main issue what that he was getting a null back from HttpContext.Current inside the parallel tasks.

ASP.NET is already multithreaded. It abstracts most of that away so that when you are writing against it you only really ever see the request you are currently dealing with. Many other requests are happening around you, but the framework does its best to shield you from that so that you can write code cleanly. It is also its downfall in some cases.

If you don’t realise what the framework is doing for you then you could very easily fall into a number of traps when you get to the edges of that abstraction. So, when someone uses HttpContext.Current inside parallel tasks not realising that there must already by multiple requests being handled, and therefore there must be multiple simultaneous HttpContext objects floating around masquerading as the Current context. It can become very difficult to track down bugs if you know what the constraints of what Current means in this… erm… context.

Ultimately, HttpContext.Current is only available on the thread that you started with in ASP.NET. If you create new threads then it is no longer available unless you explicitly set it yourself.

ASP.NET MVC – Pretty URLs

As the little Harris Benedict Calculator application stands, the only way to get some sort of answer out of it is to fill in the form. What if you wanted to pass someone a URL that takes them directly to the answer?

We could just create a controller action that takes the viewModel and have the MVC framework populate it from the URL. For example:

public ActionResult Result(HarrisBenedictViewModel viewModel)
{
    return Calculate(viewModel);
}

However, this would make the URL require a query string like this: http://localhost:42225/Main/Result?IsMale=True&Weight=75&Height=173&Age=37

This could be better.

Mapping a route for nicer URLs

What we can do is create a route to make the mapping nicer to look at than query string parameters. If we add it in before the default route it will be processed first if there is a match. So, the new RegisterRoutes method in the global.asax.cs file now looks like this:

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute("Permalink",
        "Gender/{Gender}/Weight/{Weight}/Height/{Height}/Age/{Age}",
        new { controller = "Main", action = "CalculateResult"}
        );

    routes.MapRoute(
        "Default",
        "{controller}/{action}",
        new { controller = "Main", action = "Calculate" }
    );
}

As you can see the new “Permalink” route defines a pattern that replaces parameters with properties from the view model. The controller’s action method takes in the view model that will have been populated with the values from the URL.

The controller’s action method is specified in the route as CalculateResult, and that method looks like this:

public ActionResult CalculateResult(HarrisBenedictViewModel viewModel, string gender)
{
    viewModel.IsMale = gender.ToLowerInvariant() == "male";

    return Calculate(viewModel);
}

There is actually on surprise here. Since we wanted a nice clean URL, the IsMale value is replaced with something more friendly looking. Since this isn’t in the view model, a new parameter on the action method is added to capture the value coming in from the URL. It is then processed so that the viewModel object is updated with the value that is needed.

Finally, the action calls another action, one that was created when we added our server side validation. This validates the view model and either returns the result, or if the view model is invalid directs the user to input the correct data. If the user has to fill in any data then the form will contain the values as provided in the URL and the validation messages will point out which bits need corrected.

Making a permalink on the results view

Now that we have everything set up to be able to pass around a URL with all the form values preset, it would be great to give people a way to get that link. So, on the CalculatorResults.cshtml file we are going to make that link using the HTML helper method ActionLink.

The snippet from the view looks like this:

<p>@Html.ActionLink("Calculate another?", "Calculate", "Main");
@Html.ActionLink("Permalink", "CalculateResult", new {
    Weight = Model.Weight,
    Height = Model.Height,
    Age = Model.Age,
    Gender = Model.IsMale ? "Male" : "Female" })</p>

The first action link is what was there before. The second is for the new permalink.

The first parameter is the text the user sees. The second parameter is the action method to use. When the routes are examined the first match is used, so the first route that can be determined to use the CalculateResult action method is the one we set up earlier. The third parameter is an anonymous type that provides the values to inject into the URL template provided in the RegisterRoutes method in the global.asax.cs file.

Now the user can get a permalink with nice URLs like this: http://localhost:42225/Gender/Male/Weight/75/Height/173/Age/37

Tidying things up a bit

Although we’ve got what we want, we are not going to leave things here. There is a little bit of tidying up to do first.

The action method is a little clunky. It essentially has to marshal values between the view model and the URL. The view model is a model of the view and the URL is just as valid a view as the HTML. If we can move that marshalling into the view model itself things would look better.

The HarrisBenedictViewModel class gets a new property that acts as a friendlier route to setting the IsMale property. The new property, called Gender, looks like this:

public string Gender
{
    get
    {
        return IsMale ? "Male" : "Female";
    }
    set
    {
        IsMale = (value.ToLowerInvariant() == "male");
    }
}

As a result, the action method on the controller no longer needs the extra parameter nor does it need the code to interpret that extra parameter. It now looks like this:

public ActionResult CalculateResult(HarrisBenedictViewModel viewModel)
{
    return Calculate(viewModel);
}

Finally, because the view model now contains a way to get the gender out (as well as in) the code in the cshtml file to generate the permalink can be cleaned up too. It now looks like this:

@Html.ActionLink("Permalink", "CalculateResult", new {
    Weight = Model.Weight,
    Height = Model.Height,
    Age = Model.Age,
    Gender = Model.Gender })

But why not…?

All the code in the cshtml file is doing is passing only bits of the view model to the ActionLink method, what’s wrong with just passing the whole view model. Surely it will just discard the bits it doesn’t need.

The problem is that it doesn’t know which bits it will need. If it finds properties on the view model that aren’t already in the URL template defined on the route, it will just add them as query string parameters, which makes the URL look like this:http://localhost:42225/Gender/Male/Weight/80/Height/173/Age/35?IsMale=True&BasalMetabolicRate=0&LifestyleRates=System.Collections.Generic.List%601%5BSystem.Collections.Generic.KeyValuePair%602%5BSystem.String%2CSystem.Int32%5D%5D

That list on the view model looks really ugly in the URL (and it doesn’t actually mean anything useful either).

Summary

In this post we made a new route to provide pretty URLs in order to access the resource that we needed in a permanent fashion without having to fill in the form or craft an HTTP Post. Then we tidied up the code a little in order to keep things a little cleaner.

You can download the sample code if you want to have a further play with it.

Other posts in this series

ASP.NET MVC – Server Side Validation

So far, we’ve built up a basic application and got some client side validation working. However, client side validation only goes so far. While it can prevent unnecessary trips to the server, it doesn’t prevent invalid data getting to the  server if JavaScript is turned off or if a user crafts a specific HTTP request to by pass validation.

Server side validation is quite easy, especially as we already have all the attributes attached to the view model from setting up the client side validation. The Controller class upon which our controller derives has a property called ModelState on which you can call IsValid. If true everything is okay and you can proceed. If not you need to get the user to correct the input.

The action method on the controller could change easily to something like this:

[HttpPost]
public ActionResult CalculatorResult(HarrisBenedictViewModel viewModel)
{
    if (ModelState.IsValid)
    {
        CalculateAnswer(viewModel);
        return View(viewModel);
    }

    return RedirectToAction("CalculatorInput", viewModel);
}

Note that I’ve also refactored out the calculation to a method called CalculateAnswer.

However compelling this looks, the result is a bit of a mess. If the validation fails then it redirects back to the CalculatorInput controller action via a HTTP Status 302, which causes the browser to load the URL its been given. This URL now looks something like this: http://localhost:42225/?IsMale=True&Weight=45&Height=255&Age=16&BasalMetabolicRate=0&LifestyleRates=System.Collections.Generic.List%601%5BSystem.Collections.Generic.KeyValuePair%602%5BSystem.String%2CSystem.Int32%5D%5D

Bleurgh!

Let’s look at refactoring things slightly.

Refactoring to improve server side validation

First, we want the result to come back to the same controller action (well, almost the same action) as we started with.  Also, the action name was not very well named to begin with. It is an action, however the current name is a noun phrase. Actions should be verbs (or verb phrases).

The Controller class is refactored like this:

public class MainController : Controller
{
    public ActionResult Calculate()
    {
        HarrisBenedictViewModel viewModel = new HarrisBenedictViewModel();
        return View("CalculatorInput", viewModel);
    }

    [HttpPost]
    public ActionResult Calculate(HarrisBenedictViewModel viewModel)
    {
        if (ModelState.IsValid)
        {
            CalculateAnswer(viewModel);
            return View("CalculatorResult", viewModel);
        }

        return View("CalculatorInput", viewModel);
    }

    private static void CalculateAnswer(HarrisBenedictViewModel viewModel)
    {
        double bmr = 0; // Base Metabolic Rate
        if (viewModel.IsMale)
        {
            bmr =
                66 +
                (13.7 * viewModel.Weight) +
                (5 * viewModel.Height) -
                (6.76 * viewModel.Age);
        }
        else
        {
            bmr =
                655 +
                (9.6 * viewModel.Weight) +
                (1.8 * viewModel.Height) -
                (4.7 * viewModel.Age);
        }

        viewModel.LifestyleRates.Clear();
        viewModel.LifestyleRates.Add(
            new KeyValuePair<string, int>("Sedentry", (int)(bmr * 1.2)));
        viewModel.LifestyleRates.Add(
            new KeyValuePair<string, int>("Lightly Active", (int)(bmr * 1.375)));
        viewModel.LifestyleRates.Add(
            new KeyValuePair<string, int>("Moderately Active", (int)(bmr * 1.55)));
        viewModel.LifestyleRates.Add(
            new KeyValuePair<string, int>("Very Active", (int)(bmr * 1.725)));
        viewModel.LifestyleRates.Add(
            new KeyValuePair<string, int>("Extra Active", (int)(bmr * 1.9)));
    }
}

Because the View names no longer match the name of the action then they have to be named explicitly. The URLs are based on the routing information set up in the Global.asax.cs file

Because we updated the controller action name, and we want that to be the default for the route we need to update the routes:

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute(
        "Default", // Route name
        "{controller}/{action}", // URL with parameters
        new { controller = "Main", action = "Calculate" } // Parameter defaults
    );
}

Now everything is set up to go.

When the application is run the path element of URL in the address bar remains at “/” and there is no query string. The output is much cleaner.

Summary

In this post the validation was refactored to better support server side validation and ensure that the URLs are kept clean.

The code is available for download if you want a play with it.

ASP.NET MVC 3 – Introduction to validation

In my previous post on MVC 3 I started a project to calculate a calorific intake required to maintain a stable weight. In this post I’ll extent that to add some validation to the inputs.

At the moment, since there is no validation, the use can just submit the input as it is with the default values. This produces this not so useful result:

1 - Result without validation

ASP.NET MVC 3 introduces unobtrusive client validation. It uses the data attributes available in HTML5 to store bits of data about the validation so that it can work more effectively and cleanly. If you want to enable unobtrusive client validation you need to add the following to the appSettings section in the web.config file:

<add key="ClientValidationEnabled" value="true"/>
<add key="UnobtrusiveJavaScriptEnabled" value="true"/>

Since our project is brand new (not being upgraded from a previous version of ASP.NET) then the appSettings is already there. It is also possible to enable or disable this for individual views.

You also need to add the following to the <head> section of the _Layout.chhtml file:

<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>

At this point we need to attribute the view model so that it knows what validation rules to put in place. The view model class file needs an additional using statement:

using System.ComponentModel.DataAnnotations;

Then each property can be attributed appropriately. The model is updated to look like this:

public class HarrisBenedictViewModel
{
    public HarrisBenedictViewModel()
    {
        LifestyleRates = new List<KeyValuePair<string, int>>();
    }

    public bool IsMale { get; set; }

    [Required(ErrorMessage = "Weight is required.")]
    [Range(50, 500, ErrorMessage = "Weight must be between {1}kg and {2}kg.")]
    public double Weight { get; set; }

    [Required(ErrorMessage = "Height is required.")]
    [Range(100, 250, ErrorMessage = "Height must be between {1}cm and {2}cm.")]
    public double Height { get; set; }

    [Required(ErrorMessage = "Age is required.")]
    [Range(18, 100, ErrorMessage = "Age must be between {1} and {2} years old.")]
    public int Age { get; set; }

    public double BasalMetabolicRate { get; set; }
    public IList<KeyValuePair<string, int>> LifestyleRates { get; set; }
}

As can be seen Validators can take string formatting placeholders so that if the data for the validation the message automatically updates to match, helping with the DRY principle.

The view also needs to be updated in order that the error messages are output when the user puts in incorrect data.

In the previous post, the fields in the input view looked like this:

<div class="editor-label">Height (in centimetres) </div>
<div class="editor-field">
    <input type="text" name="Height" value="@Model.Height" />
</div>

However, now we have to start using Html.EditorFor and Html.ValidationMessageFor as the validation feature adds a lot of data-* attributes to the elements in order to work.

If we change the .cshtml file to use the HTML Helper methods it looks like this:

<div class="editor-label">Height (in centimetres)</div>
<div class="editor-field">
    @Html.EditorFor(model => model.Height)
    @Html.ValidationMessageFor(model => model.Height)
</div>

And the rendered output looks a little like this (modified slightly to word-wrap on to this blog):

<div class="editor-label">Height (in centimetres)</div>
<div class="editor-field">
    <input class="text-box single-line" data-val="true"
        data-val-number="The field Height must be a number."
        data-val-range="Height must be between 100cm and 250cm." data-val-range-max="250"
        data-val-range-min="100"
        data-val-required="Height is required." id="Height" name="Height"
        type="text" value="0" />
    <span class="field-validation-valid" data-valmsg-for="Height"
        data-valmsg-replace="true"></span>
</div>

Now if the application is run up then the validation kicks in when the submit button is pressed and the user is presented with messages telling them what needs fixed in order to submit the form

2 - Result with validation

Summary

In this post I’ve introduced the concept of unobtrusive client side validation. It should be stressed that if JavaScript is disabled on the browser then validation does not take place. By the same token, if a user crafts an HTTP Post request to the server, the validation will not have taken place either.

You can download the source code if you want to have a play with it.

Starting an ASP.NET MVC 3 application

In this post, I’m going to show the basics of starting an application with ASP.NET MVC 3. The demo application will be a simple calorie counter that takes in a number of values from the user that is then used to calculate the calorific intake. The original calculation can be found here here: How many calories should I be eating?

First, if you don’t have it already, you’ll need to download ASP.NET MVC 3. Remember to shut down Visual Studio 2010 for the installation. And if you don’t have it already, I’d also recommend downloading Visual Studio 2010 SP1 and upgrading to it.

Creating the project

In Visual Studio 2010, from the New Project Dialog, go to the Visual C#/Web templates section and select ASP.NET MVC 3 Web Application from the list in the middle. If you don’t see it, ensure that the drop down says .NET Framework 4.

For this project, the Name will be set to “HarrisBenedictCalculator” as that is the type of calculation that the application will be performing.

1 - Visual Studio 2010 New Project dialog

Once the appropriate details are entered the OK button takes you to a more specific dialog for ASP.NET MVC 3 projects.

Since I want to show everything rather than rely on existing templates where some of the ground work is already done, I’m selecting the Empty template. I’m also going to select the “Use HTML5 semantic markup” and set the view engine to Razor.

Because we are selecting the empty template, unit tests project creation is not available. We can do that later.

2 - New ASP.NET MVC 3 Project dialog

When the second dialog is OK’ed the project will be created. For all that I selected “Empty” Visual Studio has created an awful lot of files already.

What’s already in this “empty” project?

3 - What's in the empty ASP.NET MVC 3 project

The project contains a set of predefined folders, some of which are already populated with files.

  • Content: Contains static content files such as CSS, graphics and javascript files.
  • Scripts: Contains a profusion of javascript files.
  • Views:  This contains some files that act like Master files for the Razor engine, an error page Razor template and a web.config.

The top level folder also contains a global.asax file which defines a set of default routes and filters, a packages.config file which is used by NuGet and a set of web.config files.

If you attempt to run the application as is then it will compile, but you go directly to a error message that says “The resource cannot be found” because there are not controllers as yet, so the routing engine cannot find a route for the default resource.

4 - Resource Not Found

For the moment, we are going to have a simple static HTML page for the error. To that end the web.config will have the following added to it:

<customErrors mode="RemoteOnly" defaultRedirect="Error.htm" />

We will see error messages, but once deployed the end users won’t. If you want to learn more about error handling see this other post on custom error handling in ASP.NET MVC 3.

Creating the initial view and controller

First up we are going to create the model of the view, the ViewModel if you like. This will contains all the variables needed to generate the request and receive data back in the response.

public class HarrisBenedictViewModel
{
    public HarrisBenedictViewModel()
    {
        LifestyleRates = new List<KeyValuePair>();
    }

    public bool IsMale { get; set; }
    public double Weight { get; set; }
    public double Height { get; set; }
    public int Age { get; set; }
    public double BasalMetabolicRate { get; set; }
    public IList<KeyValuePair<string, int>> LifestyleRates { get; set; }
}

Incidentally, I always initialise lists so that I don’t have to do a null check. Normally most code will loop over the list, an empty list will loop the same number of times as a list that isn’t there.

Now, we are ready to create the controller. When you right click on the Controllers folder in the project structure, you get an “Controller…” option in the "Add” sub-menu.

5 - Add Controller

For this, I’m going to create a controller called Main and leave it empty. That gives us a class called MainController that is derived from Controller.

The controller is going to have two actions (this is a very simple application), one called CalculatorInput which will simply return a view for accepting the values, and the other called CalculatorResult which will display the results of the calculation. Both views use the view model we created earlier.

The CalculatorInput method looks like this:

public ActionResult CalculatorInput()
{
    HarrisBenedictViewModel viewModel = new HarrisBenedictViewModel();
    return View(viewModel);
}

The empty view model will be populated by the user. If we want to pre-populate values on the view then we can do so by setting the appropriate values in the view model.

ASP.NET MVC uses naming conventions to find things. So, by default, the view will be in a folder named after the controller (in this case “Main”) and the view will be named after the controller action (in this case “CalculatorInput”).

To create the View, create the appropriate folder in the Views folder (if it doesn’t already exist) and then right click the folder you’ve just created and select Add->View…

A dialog appears that looks like this:

6 - Add View

@model HarrisBenedictCalculator.Models.HarrisBenedictViewModel

@{
    ViewBag.Title = "Harris Benedict Calculator";
}

<h2>Harris Benedict Calculator</h2>

@using(Html.BeginForm("CalculatorResult", "Main", FormMethod.Post)){
    <fieldset>
        <legend>Information about you</legend>

        <div class="editor-label">Are you male?</div>
        <div class="editor-field">@Html.CheckBox("IsMale", Model.IsMale)</div>


        <div class="editor-label">Weight (in kilos)</div>
        <div class="editor-field"><input name="Weight" value="@Model.Weight" /></div>

        <div class="editor-label">Height (in centimetres)</div>
        <div class="editor-field"><input name="Height" value="@Model.Height" /></div>

        <div class="editor-label">Age (in years)</div>
        <div class="editor-field"><input name="Age" value="@Model.Age" /></div>

        <div class="submit"><input type="submit" value="Calculate!" /></div>
    </fieldset>
}

The view sets up the form for getting the user inputs.

The Html.BeginForm defines where the form will be sent to once it is complete and how it will be sent. In this case, the form will be sent by and HTTP POST to the CalculatorResult method on the MainController class. I’ll talk more about what that does in the next section.

The form consists of a number of inputs which, by convention, have the same name as properties on the Model. If the model is pre-populated then the initial values will be used to populate the values in each of the input elements.

The CheckBox is a special case. Because of the way HTML works, if the checkbox is unchecked then nothing is returned. The MVC application then does not know if the checkbox was not ticked, or if the checkbox simply didn’t exist at all. This may be an important distinction. Therefore an Html helper method is available that outputs the checkbox and an hidden field to go with it.

At this point we can run the application and get the initial view being displayed to us:

7 - Rendering first view

Submitting the answers

As I mentioned above, the Html.BeginForm helper method tells ASP.NET MVC what controller and method to return the result to when the user presses the submit button. So, we have to create a method to process that on the specified controller (in this case Main)

The Main.CalculatorResult method looks like this:

[HttpPost]
public ActionResult CalculatorResult(HarrisBenedictViewModel viewModel)
{
    double bmr = 0; // Base Metabolic Rate
    if (viewModel.IsMale)
    {
        bmr =
            66 +
            (13.7 * viewModel.Weight) +
            (5 * viewModel.Height) -
            (6.76 * viewModel.Age);
    }
    else
    {
        bmr =
            655 +
            (9.6 * viewModel.Weight) +
            (1.8 * viewModel.Height) -
            (4.7 * viewModel.Age);
    }

    viewModel.LifestyleRates.Clear();
    viewModel.LifestyleRates.Add(
        new KeyValuePair<string, int>("Sedentry", (int)(bmr * 1.2)));
    viewModel.LifestyleRates.Add(
        new KeyValuePair<string, int>("Lightly Active", (int)(bmr * 1.375)));
    viewModel.LifestyleRates.Add(
        new KeyValuePair<string, int>("Moderately Active", (int)(bmr * 1.55)));
    viewModel.LifestyleRates.Add(
        new KeyValuePair<string, int>("Very Active", (int)(bmr * 1.725)));
    viewModel.LifestyleRates.Add(
        new KeyValuePair<string, int>("Extra Active", (int)(bmr * 1.9)));

    return View(viewModel);
}

The above performs the calculation. The code may look a bit long, but the calculation is relatively simple. In a full business application this code would be separated out elsewhere.

The method is decorated with the HttpPost attribute which tells MVC that the method may only be called in response to an HTTP POST verb. The method also takes the view model class as a parameter. MVC will may the form inputs to the view model class as best it can. You can also specify a list of more primitive types (like int, string, double, etc.) that map to the input elements on the form.

The method itself performs the calculation then updates some items in the view model with the results of the calculation. The View is then returned with the view model.

The convention is that, unless specified otherwise, the view returned will be named after the controller method in a folder named after the controller class. So the view is in the ~ViewsMain folder in a file called CalculatorResult.cshtml

@model HarrisBenedictCalculator.Models.HarrisBenedictViewModel

@{
    ViewBag.Title = "Harris Benedict Calculator Result";
}

<h2>Result</h2>

<p>For a <em>@(Model.IsMale ? "man" : "woman")</em> aged <em>@Model.Age</em> years old,
weighing <em>@Model.Weight.ToString("0.0")</em> kg, and <em>@Model.Height</em> cm tall
should be taking in the following calories per day:
</p>

<div class="result">
@foreach (var lifestyle in Model.LifestyleRates)
{
    <div class="result-line">
        <span class="result-label">@lifestyle.Key</span>@lifestyle.Value Calories
    </div>
}
</div>

<p>@Html.ActionLink("Calculate another?", "CalculatorInput", "Main")</p>

This view extracts the data from the view model and renders it to the browser.

So, the answer I get looks like this:

8 - Final Result

The Razor syntax is quite easy to follow for the most part. Anything starting with an @ sign indicates the start of some C# code. The rendering engine is clever enough to detect HTML code and revert back when needed.

At the bottom of the page the HTML helper method ActionLink generates the URL to take the user back round to the start of the process again in case they want to calculate another set of calorie intakes.

Summary

In this post I’ve demonstrated some very basic initial steps to get going with ASP.NET MVC 3.

You can also download the sample code in order to have a play yourself.