Elmah in the Enterprise: a 3 tier solution

Elmah is a fantastic error logging solution for ASP.NET, but it has one “feature” that can prevent its adoption in the enterprise – errors can be stored on the local drive or to a database, neither of which are working for my employer.

Error details should not be stored on the web server and the web server cannot be given access to the data server.

So here’s my solution, a WebApi service for the application tier. The code makes use of RestSharp despite the lack of support. The trick in this code is serializing the Error class using the BinaryFormatter and sending it over the wire as a byte array.

The Repository:

This implementation is for Sql Server but the Repository can be easily changed to use any of the other providers.

This could be enhanced to read the Elmah config section of the web.config file.

public class ElmahRepository
{
    private readonly string logConnectionString;
    private readonly string elmahApplicationName;

    public ElmahRepository(
        string LogConnectionString, 
        string ElmahApplicationNameAppSetting)
    {
        this.logConnectionString = LogConnectionString;
        this.elmahApplicationName = ElmahApplicationNameAppSetting;
    }

    public string Log(Error error)
    {
        var logger = error.ApplicationName;
        return this.Logger.Log(error);
    }

    private SqlErrorLog Logger
    {
        get
        {
            var logger = new SqlErrorLog(this.logConnectionString);
            logger.ApplicationName = this.elmahApplicationName;
            return logger;
        }
    }
}

And an integration test:

public class ElmahRepositoryTests
{
    [Fact]
    public void Log_Always_Succeeds()
    {
        var exception = new InvalidOperationException("Log_Always_Succeeds");
        var error = new Error(exception);
        var repository = this.RepositoryFactory();

        var response = repository.Log(error);
        Guid result;
        Assert.True(Guid.TryParse(response, out result));
        Assert.NotEqual(
            Guid.Parse("{00000000-0000-0000-0000-000000000000}"),
            result);
    }

    private ElmahRepository RepositoryFactory()
    {
        return new ElmahRepository(
            "server=.;database=<>;user id=<>;password=<>;",
            "Test");
    }
}

The Controller:

Note: you have to use PUT with RestSharp to get the response.

[RoutePrefix("Log")]
public class LogController : ApiController
{
    private readonly ElmahRepository elmahRepository;

    public LogController(
        ElmahRepository elmahRepository)
    {
        this.elmahRepository = elmahRepository;
    }

    [Route("Add")]
    [HttpPut]
    public string Add([FromBody]byte[] data)
    {
        return this.elmahRepository.Log(ElmahHelpers.ToError(data));
    }
}

And its integration tests

The use of NtlmAuthenticator is not mandatory.

public class LogControllerTests
{
    [Fact]
    public void Add_Always_Succeeds()
    {
        var error = new Error(
            new InvalidOperationException("Add_Always_Succeeds"));
        var controller = this.ControllerFactory();

        var response = controller.Add(ElmahHelpers.ToByteArray(error));
        Guid result;

        Assert.True(Guid.TryParse(response, out result));
        Assert.NotEqual(
            Guid.Parse("{00000000-0000-0000-0000-000000000000}"),
            result);
    }

    [Fact]
    public void Add_MadeAsARestRequest_Succeeds()
    {
        var error = new Error(
            new InvalidOperationException("Add_MadeAsARestRequest_Succeeds"));
        var client = this.RestClientFactory();
        var request = new RestRequest("Log/Add");
        request.RequestFormat = DataFormat.Json;
        request.AddBody(ElmahHelpers.ToByteArray(error));

        var response = client.Put(request).Content.Replace(@"""", "");

        Guid result;
        Assert.True(Guid.TryParse(response, out result));
        Assert.NotEqual(
            Guid.Parse("{00000000-0000-0000-0000-000000000000}"),
            result);
    }

    private RestClient RestClientFactory()
    {
        var client = new RestClient("http://<server>/<path>/");
        client.Authenticator = new NtlmAuthenticator();

        return client;
    }

    private LogController ControllerFactory()
    {
        var controller = new LogController(
            this.ElmahRepositoryFactory());

        var context = new HttpControllerContext
        {
            RequestContext = new HttpRequestContext
            {
                Principal = new GenericPrincipal(
                    System.Security.Principal.WindowsIdentity.GetCurrent(),
                    null)
            }
        };

        controller.ControllerContext = context;
        return controller;
    }

    private ElmahRepository ElmahRepositoryFactory()
    {
        return new ElmahRepository(
            "server=.;database=<>;user id=<>;password=<>;",
            "Test");
    }
}

The BinaryFormatter helpers:

public static class ElmahHelpers
{
    public static byte[] ToByteArray(Error error)
    {
        var bf = new BinaryFormatter();
        using (var ms = new MemoryStream())
        {
            bf.Serialize(ms, error);
            return ms.ToArray();
        }
    }

    public static Error ToError(byte[] data)
    {
        using (var memStream = new MemoryStream())
        {
            var binForm = new BinaryFormatter();
            memStream.Write(data, 0, data.Length);
            memStream.Seek(0, SeekOrigin.Begin);
            var obj = (Error)binForm.Deserialize(memStream);
            return obj;
        }
    }
}

The implementation of ErrorLog that calls the WebApi controller:

I have simply chosen to throw an UnauthorizedAccessException if any attempt is made to read the errors.

public class RestErrorLog : ErrorLog
{
    private readonly string connectionString;

    public RestErrorLog(IDictionary config)
    {
        if (config == null)
        {
            throw new ArgumentNullException("config");
        }

        this.connectionString = (string)config["connectionString"] ?? string.Empty;

        if (this.connectionString.Length == 0)
        {
            throw new Elmah.ApplicationException("Connection string is missing for the Rest error log.");
        }
    }

    public override string Name
    {
        get
        {
            return "Rest Error Log.";
        }
    }

    public override string Log(Error error)
    {
        var client = new RestClient(this.connectionString);
        client.Authenticator = new NtlmAuthenticator();
        var request = new RestRequest("Log/Add");
        request.RequestFormat = DataFormat.Json;
        request.AddBody(ToByteArray(error));

        var result = client.Put(request).Content.Replace(@"""", "");

        return result;
    }

    public override int GetErrors(int pageIndex, int pageSize, System.Collections.IList errorEntryList)
    {
        throw new UnauthorizedAccessException(
            string.Format("RestErrorLog.GetErrors({0}, {1})", pageIndex, pageSize));
    }

    public override ErrorLogEntry GetError(string id)
    {
        throw new UnauthorizedAccessException(
            string.Format("RestErrorLog.GetError({0})", id));
    }

    private static byte[] ToByteArray(Error error)
    {
        var bf = new BinaryFormatter();
        using (var ms = new MemoryStream())
        {
            bf.Serialize(ms, error);
            return ms.ToArray();
        }
    }
}

And finally the entry in web.config to wire it all together:

Note that applicationName should match the value injected into the Repository.

<elmah xmlns="http://Elmah.Configuration">
  <errorLog 
    type="<namespace>.RestErrorLog, <assembly>" 
    applicationName="Test" 
    connectionString="http://<server>/<path>/"></errorLog>
</elmah>

Woohoo! Elmah in the Enterprise :-)

Trying to get JetPack Markdown with code to play nicely with WordPress

After a lot of trial and error here’s how I got code in markdown to work in WordPress.

2 plug-ins are required

Smart Syntax for adding class="prettyprint lang-xyz to the <pre> tag

and

Prettify Code Syntax for the most flexible syntax highlighter I have ever found for WordPress.

Finally, go to Settings - Prettify Code Syntax and change the top of the Custom css to this

.prettyprint .com       { color: #008000; }
.prettyprint .str, .tag { color: #A31515; }
.prettyprint .kwd, .atv { color: #0000FF; }
.prettyprint .typ       { color: #2B91AF; }
.prettyprint .lit, .atn { color: #FF0000; }
.prettyprint .pun, .pln { color: #000000; }
.prettyprint .dec       { color: #800080; }

pre.prettyprint, 
code.prettyprint, 
pre.prettyprint code,
.post-content pre.prettyprint,
.post-content code.prettyprint,
.post-content pre.prettyprint code,
.comment-content pre.prettyprint,
.comment-content code.prettyprint,
.comment-content pre.prettyprint code  {
    background-color: #F6F6F6; display: block;
}

It’s ok but there still problems with the <pre> tags being rendered differently between the home page and the individual post page and it shrinks down to almost nothing on a mobile device.

Building a Func<TEntity, bool> delegate from an anonymous object

The background to this code is that I’m getting rid of Entity Framework – it’s too slow and IQueryable is so cool but ends up sucking by slowly bleeding into the code base and thereby becoming difficult to performance tune.

Thanks, as always, go to my friend .NETJunkie for his remarkable post on the query pattern that has led me to this design pattern. I have my own variation on the theme that I will post at some point in time … but I digress …

I’m migrating all my code to use the query pattern by implementing IQueryHandler<> and will use Dapper to access the database. I will be implementing local caching using a simple decorator over the relevant IQueryHandler<>‘s and that is the point of this post.

Dapper takes a query and an anonymous object. What I plan to do is intercept calls to Dapper and check the local cache for the entit(y/ies) being requested before going to the database. To start with the cache will be a simple List<TEntity>. To find something in a list we use Linq. To use Linq I need to convert each anonymous object into a delegate that can be passed into the Where extension method of List<TEntity> (a Func<TEntity, bool>). For now I only plan to support ==[&& ==[&& ==[...]]] queries.

Dapper is a simple, super fast, data mapper implementation.

var dog = connection.Query<Dog>("select Id = @Id", new { Id = 1 });

To the code.

The standard abstractions (the delegate builder is a standard query handler)

public interface IQuery<TResult>
{
}

public interface IQueryHandler<TQuery, TResult> 
    where TQuery : IQuery<TResult>
{
    TResult Execute(TQuery query);
}

The generic parameter object for the EqualsDelegateBuilder query handler

public class EqualsDelegate<TEntity> : IQuery<Func<TEntity, bool>>
{
    public object query { get; set; }
}

And the query handler that will create a Func<TEntity, bool> from an anonymous object

public class EqualsDelegateBuilder<TEntity> : 
    IQueryHandler<EqualsDelegate<TEntity>, Func<TEntity, bool>>
{
    public Func<TEntity, bool> Execute(EqualsDelegate<TEntity> query)
    {
        object o = query.query;
        var type = o.GetType();
        var props = type.GetProperties()
            .Where(p => p.GetIndexParameters().Length == 0).ToArray();

        ParameterExpression pe = Expression.Parameter(typeof(TEntity), "x");
        Expression expression = 
            CreatePropertiesEqualValuesExpression<TEntity>(pe, props, o);

        var lambda = Expression.Lambda<Func<TEntity, bool>>(expression, pe);

        return lambda.Compile();
    }

    private Expression CreatePropertiesEqualValuesExpression<TEntity>(
        ParameterExpression pe,
        PropertyInfo[] props,
        object o)
    {
        Expression result = null;

        foreach (var prop in props)
        {
            Expression expression = 
                CreatePropertyEqualsValueExpression<TEntity>(pe, prop, o);
            result = result == null
                ? expression
                : Expression.AndAlso(result, expression);
        }

        return result;
    }

    private Expression CreatePropertyEqualsValueExpression<TEntity>(
        ParameterExpression pe,
        PropertyInfo prop,
        object o)
    {
        Expression left = 
            Expression.Property(pe, typeof(TEntity).GetProperty(prop.Name));
        Expression right;
        if (typeof(TEntity).GetProperty(prop.Name).PropertyType == typeof(long))
        {
            right = Expression.Constant(
                Convert.ToInt64(prop.GetValue(o, null)),
                typeof(TEntity).GetProperty(prop.Name).PropertyType);
        }
        else
        {
            right = Expression.Constant(prop.GetValue(o, null), prop.PropertyType);
        }

        return Expression.Equal(left, right);;
    }
}

This is the test data

private readonly DateTime date = DateTime.Parse("31 jul 2014");
private readonly Guid uid = Guid.NewGuid();

public class DataEntity
{
    public long Id { get; set; }
    public string Name { get; set; }
    public DateTime Date { get; set; }
    public Guid Uid { get; set; }
}

private IEnumerable<DataEntity> Entities()
{
    return new DataEntity[]
    {
        new DataEntity{ Id = 1, Name = "name", Date = this.date, Uid = Guid.NewGuid() },
        new DataEntity{ Id = 2, Name = "stuff", Date = this.date.AddDays(1), Uid = this.uid },
        new DataEntity{ Id = 3, Name = "also", Date = this.date.AddDays(2), Uid = this.uid },
        new DataEntity{ Id = 4, Name = "else", Date = this.date, Uid = Guid.NewGuid() },
        new DataEntity{ Id = 5, Name = "name", Date = this.date, Uid = Guid.NewGuid() },
    };
}

The methods that call the delegate builder and filter the data

public Func<TEntity, bool> BuildDelegate<TEntity>(object o)
{
    var handler = new EqualsDelegateBuilder<TEntity>();
    var query = new EqualsDelegate<TEntity>
    {
        query = o
    };

    return handler.Execute(query);
}

public DataEntity Get(object o)
{
    return this.GetAll(o).FirstOrDefault();
}

public IEnumerable<DataEntity> GetAll(object o)
{
    return this.Entities().Where(this.BuildDelegate<DataEntity>(o)).ToList();
}

And the tests

[Fact]
public void Get_ById_Succeeds()
{
    var result = this.Get(new { Id = 1 });
    Assert.NotNull(result);
}

[Fact]
public void Get_ByName_Succeeds()
{
    var result = this.GetAll(new { Name = "name" });
    Assert.Equal(2, result.Count());
}

[Fact]
public void Get_ByDate_Succeeds()
{
    var result = this.GetAll(new { Date = this.date });
    Assert.Equal(3, result.Count());
}

[Fact]
public void Get_ByGuid_Succeeds()
{
    var result = this.GetAll(new { Uid = this.uid });
    Assert.Equal(2, result.Count());
}

[Fact]
public void Get_ByMultipleProperties_Succeeds()
{
    var result = this.GetAll(new { Id = 2, Uid = this.uid });
    Assert.Equal(1, result.Count());
}

Migrating from NUnit to xUnit

These regular expression came in handy recently – they’re not perfect, in particular a couple of the second grouping need to be more greedy – but I did the migration first time through so didn’t get to improve them.

Find: Assert.That((.+?), Is.EqualTo((.+?)))
Replace: Assert.Equal($2, $1)

Find: Assert.That((.+?) == (.+?))
Replace: Assert.Equal($2, $1)

Find: Assert.That((.+?), Is.StringContaining((.+)))
Replace: Assert.Contains($2, $1)

Find: Assert.That((.+?).Contains((.+)))
Replace: Assert.Contains($2, $1)

Find: Assert.That((.+?), Is.GreaterThanOrEqualTo((.+)))
Replace: Assert.True($1 >= $2)

Find: Assert.That((.+?), Is.Not.Null)
Replace: Assert.NotNull($1)

Find: Assert.That((.+?), Is.Null)
Replace: Assert.Null($1)

Find: Assert.That((.+?), Is.True)
Replace: Assert.True($1)

Find: Assert.That((.+?), Is.False)
Replace: Assert.False($1)

markdown in WordPress – AT LAST!!!!!

Here’s some normal text interspersed with some Code, some italics and bold.

a quote

some sql

select
    a.FILEID,
    [FILE_SIZE_MB] = 
        convert(decimal(12,2),round(a.size/128.000,2)),
    [SPACE_USED_MB] =
        convert(decimal(12,2),round(fileproperty(a.name,'SpaceUsed')/128.000,2)),
    [FREE_SPACE_MB] =
        convert(decimal(12,2),round((a.size-fileproperty(a.name,'SpaceUsed'))/128.000,2)) ,
    NAME = left(a.NAME,15),
    FILENAME = left(a.FILENAME,30)
from
    dbo.sysfiles a

some code

[TestFixture]
public class ScrewdriverTests
{
    [Test]
    public void Container_ExplicitRegistration1_ReturnsExpectedClass()
    {
        Container container = new Container();

        container.Register(typeof(IScrewdriver<FlatHead>), typeof(FlatHeadScrewdriver));

        var screwdriver = container.GetInstance(typeof(IScrewdriver<FlatHead>));

        Assert.That(screwdriver, Is.Not.Null);
    }

    [Test]
    public void Container_ExplicitRegistration2_ReturnsExpectedClass()
    {
        Container container = new Container();

        container.Register<IScrewdriver<FlatHead>, FlatHeadScrewdriver>();

        var screwdriver = container.GetInstance<IScrewdriver<FlatHead>>();

        Assert.That(screwdriver, Is.Not.Null);
    }

    [Test]
    public void Container_ExplicitRegistration_ExceptionForUnregisteredClass()
    {
        Container container = new Container();

        container.Register<IScrewdriver<FlatHead>, FlatHeadScrewdriver>();

        Assert.Throws<ActivationException>(() =>
            {
                var screwdriver = container.GetInstance<IScrewdriver<Torx>>();
            });
    }

    [TestCase(typeof(IScrewdriver<FlatHead>))]
    [TestCase(typeof(IScrewdriver<Phillips>))]
    [TestCase(typeof(IScrewdriver<Torx>))]
    public void Container_BatchRegistration_ReturnsExpectedClass(Type registeredType)
    {
        Container container = new Container();

        container.RegisterManyForOpenGeneric(
            typeof(IScrewdriver<>), 
            typeof(IScrewdriver<>).Assembly);

        var screwdriver = container.GetInstance(registeredType);
        Assert.That(screwdriver, Is.Not.Null);
    }
}

and some xml too

<?xml version="1.0"?>
<configuration>
  <configSections>
    <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=4.4.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false"/>
  </configSections>
  <connectionStrings>
    <add name="PPContext" connectionString="Data Source=.;Initial Catalog=PP;Integrated Security=True;MultipleActiveResultSets=True"
      providerName="System.Data.SqlClient" />
  </connectionStrings>
  <entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework"/>
  </entityFramework>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
  </startup>
</configuration>

Microsoft’s Task Parallel Library and the principle behind node.js

I wanted to see how Microsoft’s Task Parallel Library compared with node.js in so far as passing the next method in to the current to chain the calls indefinitely. So I created a method that iteratively adds itself to the current executing Task. The initial test was to see if the code would fail with a StackOverflowException but what I found instead was that I couldn’t get the Task to Wait unless I put the thread to sleep.

So this simple test fails, every time:

private volatile int count = 0;

[Test]
public void Wait_RecursiveAdditionalContinueWith_Waits()
{
    var start = new Task(() => { });
    start.ContinueWith(ContinuationMethod);

    start.Start();
    start.Wait();

    Assert.That(this.count, Is.EqualTo(100));
}

private void ContinuationMethod(Task task)
{
    count++;
    if (this.count < 100)
    {
        task.ContinueWith(ContinuationMethod);
    }
}

But if I swap start.Wait(); with Thread.Sleep(10); then it works fine. WFT? To cut a long story short … the ContinueWith method returns a child Task that you also need to wait for.

[Test]
public void Wait_RecursiveAdditionalContinueWith_Waits2()
{
    var start = new Task(() => { });
    var child = start.ContinueWith(ContinuationMethod2);

    start.Start();
    child.Wait();

    Assert.That(this.count, Is.EqualTo(100));
}

private void ContinuationMethod2(Task task)
{
    count++;
    if (this.count < 100)
    {
        var child = task.ContinueWith(ContinuationMethod2);
        child.Wait();
    }
}

Obvious once you know!

So, back to the initial question – how long for a StackOverflowException? I can’t get it to fail …

[Test]
public void Wait_RecursiveAdditionalContinueWith_Waits3()
{
    var start = new Task(() => { });
    var child = start.ContinueWith(ContinuationMethod3);

    start.Start();
    child.Wait();

    Assert.That(this.count, Is.EqualTo(100000000));
}

private void ContinuationMethod3(Task task)
{
    count++;
    if (this.count < 100000000)
    {
        var child = task.ContinueWith(ContinuationMethod3);
        child.Wait();
    }
}

Sql Server Shrink Log File

Easy with Simple Recovery

DBCC SHRINKFILE ("<FileName>_Log", 1);
GO

otherwise

http://social.technet.microsoft.com/Forums/sqlserver/en-US/0a7a7fc5-d30e-4841-8ed1-84676b575e55/sql-server-2012-how-to-shrink-the-database-transaction-log

USE AdventureWorks2008R2;
GO
-- Truncate the log by changing the database recovery model to SIMPLE.
ALTER DATABASE AdventureWorks2008R2
SET RECOVERY SIMPLE;
GO
-- Shrink the truncated log file to 1 MB.
DBCC SHRINKFILE (AdventureWorks2008R2_Log, 1);
GO
-- Reset the database recovery model.
ALTER DATABASE AdventureWorks2008R2
SET RECOVERY FULL;
GO

node.js calling multiple web services in parallel

http://askhds.blogspot.co.uk/2012/02/nodejs-rest-call-using-http-library.html

var http = require('http');
// Add helloworld module
var helloworld = require('helloworld_mod');
 
http.createServer(function(req, res) {
 
  res.writeHead(200, {
    'Content-Type' : 'text/xml'
  });
 
  try {
    // Bypass function call to "Google Maps API"
    getFromGoogle(req, res);
  }
 
  catch (e) {
    res.end("Try again later");
  }
 
}).listen(1337, '127.0.0.1');
 
console.log('Server running at http://127.0.0.1:1337/');
 
console.log('Type the URL in address bar');
console.log('http://127.0.0.1:1337/maps/api/geocode/xml?' 
+ 'address=1600+Amphitheatre+Parkway,+Mountain+View,+CA&sensor=false');
 
function getFromGoogle(mainreq, mainres) {
  // http://maps.googleapis.com/maps/api/geocode/
  // xml?address=1600+Amphitheatre+Parkway,+Mountain+View,+CA&sensor=true_or_false
 
  var options = {
    host : 'maps.googleapis.com',
    port : 80,
    path : mainreq.url,
    method : 'GET'
  };
 
  var req = http.request(options);
  var result = '';
 
  req.on('response', function(response) {
    response.setEncoding('utf8');
    response.on('data', function(chunk) {
      result += chunk;
    });
 
    response.on('end', function() {
      mainres.end(result);
    });
  });
 
  req.on('error', function(e) {
    console.log('problem with request: ' + e.message);
  });
 
  req.end();
}

http://stackoverflow.com/questions/19273700/how-to-sync-call-in-node-js

var array = [1, 2, 3];
var data = 0;
var cntr = 0;

function countnExecute() {
    if (++cntr === array.length)
        executeOtherFunction(data);
}

for(var i = 0; i < array.length; i++){
    asyncFunction(data++, countnExecute);
}

Extract details from an Expression

I wanted to come up with a way of establishing the type name and property name when applying general validations within my code. So, for example for this validation:.

var bool = Requires.IsNotNull(user.lastName)

I have to explicitly code the exception:

throw NullReferenceException("User.lastName")

What I’d like is for all this to happen when I declare the test, without double typing the type and property name.

This is still very much a work in progress but I’ve got the basics of what I’m trying to achieve by using the Expression class.

Here’s how it’s used:

[Test]
public void FirstTest()
{
    var user = new User()
    {
        Name = "John",
        Age = 32,
        Skills = new List<string> { "digging", "mowing", "pruning" }
    };

    var decorator = new NaiveExpressionDecorator<User>(x => x.Name != null);

    decorator.propertyName.Should().Be("User.Name");
}

And here’s the basic implementation:

public sealed class NaiveExpressionDecorator<T>
{
    private readonly Expression<Func<T, bool>> rule;
    private readonly Func<T, bool> compiled;

    public NaiveExpressionDecorator(Expression<Func<T, bool>> rule)
    {
        this.rule = rule;
        compiled = this.rule.Compile();
    }

    public string propertyName
    {
        get
        {
            return PropertyName(this.rule.Body as dynamic);
        }
    }

    public bool Execute(T instance)
    {
        return compiled(instance);
    }

    private string PropertyName(BinaryExpression expression)
    {
        return PropertyName(expression.Left as dynamic);
    }

    private string PropertyName(MethodCallExpression expression)
    {
        if (expression.Object == null)
        {
            return PropertyName(expression.Arguments[0] as dynamic);
        }
        return PropertyName(expression.Object as dynamic);
    }

    private string PropertyName(MemberExpression expression)
    {
        string typeName = expression.Expression.Type.Name;
        return typeName + "." + expression.Member.Name;
    }
}

This is working for these tests:

private List<Tuple<Expression<Func<User, bool>>, string>> TestCases()
{
    return new List<Tuple<Expression<Func<User, bool>>, string>> {
        new Tuple<Expression<Func<User, bool>>, string>(
            x => x.Skills.Count() > 0, "User.Skills"),
        new Tuple<Expression<Func<User, bool>>, string>(
            x => x.Skills.Where(s => s.Length > 0).Contains("pruning"), "User.Skills"),
        new Tuple<Expression<Func<User, bool>>, string>(
            x => x.Age > 20, "User.Age"),
        new Tuple<Expression<Func<User, bool>>, string>(
            x => x.Name != null, "User.Name"),
        new Tuple<Expression<Func<User, bool>>, string>(
            x => x.Name == "John", "User.Name"),
        new Tuple<Expression<Func<User, bool>>, string>(
            x => x.Skills.Contains("mowing"), "User.Skills")};
}