Shannon Deminick's blog all about .Net, Umbraco & Web development

PetaPoco can cause high memory usage with certain queries

September 25, 2014 09:51

If you are using PetaPoco, or NPoco (which seams to be the most up-to-date fork of the project), the title of this post might be a bit scary… but hopefully you won’t have to worry. This really depends on how you create your queries and how many different query structures you are executing.

High memory usage

Here is the code in relation to the memory growth when using PetaPoco:

What is happening here is that every time a POCO needs to be mapped from a data source, this will add more values to a static cache, specifically this one:  (m_PocoDatas)

This isn’t a bad thing… but it can be if you are:

  • using non-parameterized where clauses
  • you have dynamically generated where clauses
  • you use a lot of sql ‘IN’ clauses – since the items in the array being passed to the ‘IN’ clauses is dynamic
  • you have tons of differently statically unique where clauses

Each time a unique SQL query is sent to PetaPoco it will store this SQL string and associate it to a delegate (which is also cached). Over time, as these unique SQL queries are executed, the internal static cache will grow. In some cases this could consume quite a lot of memory.

The other thing to note is how large the ‘key’ that PetaPoco/NPoco uses:

var key = string.Format("{0}:{1}:{2}:{3}:{4}", sql, connString, ForceDateTimesToUtc, firstColumn, countColumns);

Considering how many queries might be executing in your application, the storage for these keys alone could take up quite a lot of memory! An SQL statement combined with a connection string could be very long, and each of these combinations gets stored in memory for every unique SQL query executed that returns mapped POCO objects.

Parameterized queries vs. non-parameterized

Here’s some examples of why non-parameterized queries will cause lots of memory consumption. Lets say we have a simple query like:

db.Query<MyTable>("WHERE MyColumn=@myValue", new {myValue = "test"})

Which results in this SQL:

SELECT * FROM MyTable WHERE MyColumn = @myValue

This query can be used over and over again with a different value and PetaPoco will simply store a single SQL key in it’s internal cache. However, if you are executing queries without real parameters such as:

db.Query<MyTable>("WHERE MyColumn='hello'");
db.Query<MyTable>("WHERE MyColumn='world'");
db.Query<MyTable>("WHERE MyColumn='hello world'");

Which results in this SQL:

SELECT * FROM MyTable WHERE MyColumn = 'hello';
SELECT * FROM MyTable WHERE MyColumn = 'world';
SELECT * FROM MyTable WHERE MyColumn = 'hello world';

Then PetaPoco will store each of these statements against a delegate in it’s internal cache since each of these string statements are not equal to each other.

Depending on your application you still might have a very large number of unique parameterized queries, though I’d assume you’d have to have a terrifically huge amount for it to be a worry.

Order by queries

Unfortunately even if you use parameterized queries, PetaPoco will store the SQL query key with it’s Order By clause which isn’t necessary and will again mean more duplicate SQL keys and delegates being tracked. For example if you have these resulting queries:

SELECT * FROM MyTable WHERE MyColumn = @myValue ORDER BY SomeField;
SELECT * FROM MyTable WHERE MyColumn = @myValue ORDER BY AnotherField;

PetaPoco will store each of these statements in it’s internal cache separately since the strings don’t match, however the delegate that PetaPoco is storing against these SQL statements isn’t concerned about the ordering output, it’s only concerned about the column and table selection so in theory it should be stripping off the last Order By clause (and other irrelevant clauses) to avoid this duplication.

A slightly better implementation

First, if you are using PetaPoco/NPoco, you shouldn’t use dynamic queries for the point’s mentioned above. If you need this functionality then I suppose it might be worth these libraries adding some sort of property on the Database object or a parameter in either the Fetch or Query methods to specify that you don’t want to use the internal cache (this will be slower, but you won’t get unwanted memory growth). I’d really just suggest not using dynamically created where clauses ;-)

Next, there’s a few things that could be fixed in the PetaPoco/NPoco core to manage memory a little better:

  • The size the the key that is stored in memory doesn’t need to be that big. A better implementation would be to use a hash combiner class to combine the GetHashCode result of each of those parameters that make up the key. This is a very fast way to create a hash of some strings that will result in a much smaller key. An example of a hash combiner class is here (which is actually inspired by the various internal hash code combiner classes in .Net):
  • Instead of storing all of this cache in static variables, have them stored in an ObjectCache/MemoryCache ( with a sliding expiration so the memory can get collected when it’s unused
  • The Order By clause should be ignored based on the point mentioned above

I’ve created a PR for NPoco here, and also created an issue on the original PetaPoco source here.

ASP.Net Identity for Umbraco

August 7, 2014 01:31

I’ve released version 1.0 of UmbracoIdentity which allows for ASP.Net Identity to be used with Umbraco for front-end members. I’ve tried to write enough documentation for you to get started, all of the code and docs are here:

It’s worth noting that this is not something that ‘everyone’ should just jump in with and start using. If you are not familiar with OWIN or ASP.Net Identity than none of this will really make any sense, I’ve added a bit of a disclaimer to the docs about this here:

There are some known issues and limitations that you should be aware of, and this will also not work currently with back office users (that will come eventually too though).

This package can be highly customized, it comes with many .cshtml views and c# classes that you can customize as you see fit – very similar to the Visual Studio 2013 Web Application templates that support ASP.Net Identity.

What about Asp.Net Membership with Umbraco?

The way that I’ve created this is to be 100% compatible with the current Membership structure in Umbraco. This means that this is not using EntityFramework to access data, it uses the Umbraco member services and providers using custom ASP.Net Identity user stores. This also means that the password formats are based on the current password formats of the membership provider. When the Nuget package is installed it will actually swap out the membership provider for a custom type: UmbracoIdentity.IdentityEnabledMembersMembershipProvider. This is required so that the password security can still be handled by the membership provider logic.

There is a note about passwords here, ASP.Net Identity normally will format and salt passwords different (slightly better) than how the membership providers current work, but if you need that functionality you’d have to implement your own IPasswordHasher.


It is absolutely essential you read the documentation before installing. Once you’ve done that, you can use Nuget:

PM> Install-Package UmbracoIdentity

ClientDependency 1.8 released

July 7, 2014 08:02

It’s taken me forever to get this release out purely due to not having enough time, but here it finally is. This update now multi-targets framework versions:

  • Core project now targets both .Net 4 and 4.5
  • MVC project is now targets both .Net 4 and 4.5 for MVC 4 and .Net 4.5 for MVC 5

There are also a couple of minor bug fixes:

The update to the CDF .Less project is the update to use the latest .Less version.

To install the CDF core:

PM> Install-Package ClientDependency

To install CDF for MVC (less than v5):

PM> Install-Package ClientDependency-MVC

If you are using MVC 5 then you’ll need to use the MVC 5 specific version:

PM> Install-Package ClientDependency-MVC5

To install the .Less update:

PM> Install-Package ClientDependency-Less

Remember CDF also supports TypeScript, CoffeeScript and SASS!

PM> Install-Package ClientDependency-TypeScript

PM> Install-Package ClientDependency-CoffeeScript

PM> Install-Package ClientDependency-SASS

Multiple WebApi controllers with the same name but different namespaces

June 27, 2014 05:56

Warren recently reported this issue on Umbraco which prohibits WebApi from routing to two different paths that specify the same controller name but different namespaces. This type of thing is fully supported in MVC but not in WebApi for some reason.

Here’s a quick example, suppose we have two controllers:

namespace Test1
    public class ConfigController : UmbracoApiController
        public int GetStuff()
            return 9876;
namespace Test2
    public class ConfigController : UmbracoApiController
        public int GetStuff()
            return 1234;

These controller definitions will create routes to the following paths respectively:

  • /umbraco/backoffice/test1/config/getstuff
  • /umbraco/backoffice/test2/config/getstuff

When these routes are created, the “Namespaces” data token is specified on the route, just like what is done in MVC, however in WebApi that needs to be done manually. Example:

var r = routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{id}",
    defaults: new { id = RouteParameter.Optional }
r.DataTokens["Namespaces"] = new string[] {"Foo"};

but if you navigate to either of these paths you’ll end up with a message like:

Multiple types were found that match the controller named 'Config'. This can happen if the route that services this request ('umbraco/backoffice/Test2/Config/{action}/{id}') found multiple controllers defined with the same name but differing namespaces, which is not supported. The request for 'Config' has found the following matching controllers: Test1.ConfigController Test2.ConfigController

Custom IHttpControllerSelector

To achieve what we want, we need to create a custom IHttpControllerSelector. I’ve created this in the Umbraco core to solve the issue and the source can be found HERE. The implementation is pretty straight forward – it relies on the default WebApi controller selector for everything unless a “Namespaces” data token is detected in the route and more than one controller type was found for the current controller name in the app domain.

There’s some posts out there that elude to the possibility of this being supported in WebApi in the future but as of the latest source code for the DefaultHttpControllerSelector, it appears that the functionality is not yet there.

If you need this functionality though, this implementation is working and pretty simple. To register this selector just use this code on startup:

    new NamespaceHttpControllerSelector(GlobalConfiguration.Configuration));

This blog now powered by Articulate

June 26, 2014 04:14

I’ve recently decided to build a new open source blog engine powered by Umbraco called Articulate. There’s a few reasons why i wanted to do this:

  • Since my full time job is an Umbraco core developer, I spend most of my time building Umbraco and get very little time for using Umbraco. I wanted to change this dilemma and really use Umbraco and utilize many of the features we’ve been creating and try to push some of it’s boundaries. For me this is a perfect way to find inspiration for new Umbraco features and enhancements.
  • I’ve wanted to move my blog away from BlogEngine.Net to Umbraco for quite some time (dogfooding) but I really needed to have every feature that I use in BlogEngine.Net available
  • I wanted to make the blog experience as simple as possible in Umbraco
  • I wanted to be able to write blog posts directly from my mobile phone easily using the web

I’ve got some documentation written and I’ll keep updating this over time but hopefully there’s enough there to get you started. Since Articulate is open source and hosted on GitHub, any community contributions are hugely welcomed :) Whether that’s core code additions, fixes, documentation, etc… any contribution is a big help.

Articulate templates are based on themes and I think it would be super awesome if people started creating their own themes and releasing them as their own packages or including them in the Articulate core for release. Creating themes is really easy and in fact a few of the themes included with Articulate are open source MIT licensed themes migrated over from the Ghost blogging platform (which is also very easy to do).

The first version of Articulate is out and can be downloaded either from the Umbraco package repository or from GitHub. There are a few minor bugs in this release that have been reported and fixed and I’ll have a newer version out this week.

Custom MVC routes within the Umbraco pipeline

May 24, 2014 02:03

A while ago I wrote a post on how to do custom MVC routing in Umbraco, though the end result wasn’t quite ideal. There were a few tricks required and It wasn’t perfect since there were problems with rendering macros on the resulting view, etc… This was due to not having a PublishedContentRequest object assigned to the context. So then we went ahead and created a new attribute to assign to your MVC action to resolve this: [EnsurePublishedContentRequestAttribute]

Like the last post, you can read a lot about all of this in this Our thread. With the [EnsurePublishedContentRequestAttribute] attribute you could now assign any IPublishedContent instance to a PublishedContentRequest and be sure that it was assigned to the UmbracoContext. But this still isn’t the most ideal way to go about specifying MVC routes to work within the Umbraco pipeline… so I’ve created the following implementation which works quite well.


A little bit of background in to custom MVC routes and Umbraco… The reason why it is not terribly straight forward to create a custom route and have it assigned to an Umbraco node is because the node doesn’t exist at your custom route’s location.

For example, if we have this route:

//Create a custom route
            controller = "MyProduct", 
            action = "Product", 
            sku = UrlParameter.Optional

Umbraco by default would have no idea what node (IPublishedContent) would be assigned to this. The way Umbraco relates a URL to an IPublishedContent instance is by a list of IContentFinder’s. A very easy way to relate a custom URL to an IPublishedContent instance is to create your own IContentFinder. Combine that with route hijacking and in many cases this would probably be enough for your custom routing needs. However, it does not solve how you would wire up custom route parameters to your controller like how MVC normally works. Like in the above routing example, you’d want to have the ‘sku’ parameter value wired up to your Action parameter.

The above route can work and be integrated into Umbraco by following some aspects of my previous blog post and use the [EnsurePublishedContentRequestAttribute], but we can make it easier…

Creating routes

The simplest way to demonstrate this new way to create MVC routes in Umbraco is to just show you an example, so here it is:

//custom route
        controller = "MyProduct",
        sku = UrlParameter.Optional
    new ProductsRouteHandler(_productsNodeId));

This is using a new extension method: MapUmbracoRoute which takes in the normal routing parameters (you can also include constraints, namespaces, etc….) but also takes in an instance of UmbracoVirtualNodeRouteHandler.

The instance of UmbracoVirtualNodeRouteHandler is responsible for associating an IPublishedContent with this route. It has one abstract method which must be implemented:

IPublishedContent FindContent(RequestContext requestContext, UmbracoContext umbracoContext)

It has another virtual method that can be overridden which will allow you to manipulate the PublishedContentRequest however you’d like:

PreparePublishedContentRequest(PublishedContentRequest publishedContentRequest)

So how do you find content to associate with the route? Well that’s up to you, one way (as seen above) would be to specify a node Id. In the example my ProductsRouteHandler is inheriting from UmbracoVirtualNodeByIdRouteHandler which has an abstract method:

IPublishedContent FindContent(RequestContext requestContext, UmbracoContext umbracoContext, 
    IPublishedContent baseContent);

So based on all this information provided in these methods, you can associate whatever IPublishedContent item you want to the request.

Virtual content

This implementation expects any instance of IPublishedContent, so this means you can create your own virtual nodes with any custom properties you want. Generally speaking you’ll probably have a real Umbraco IPublishedContent instance as a reference point, so you could create your own virtual IPublishedContent item based on PublishedContentWrapped, pass in this real node and then just override whatever properties you want, like the page Name, etc..

Whatever instance of IPublishedContent returned here will be converted to a RenderModel for use in your controllers.


Controllers are straight forward and work like any other routed controller except that the Action will have an instance of RenderModel mapped to it’s parameter. Example:

public class MyProductController : RenderMvcController
    public ActionResult Product(RenderModel model, string sku)
        //in my case, the IPublishedContent attached to this
        // model will be my products node in Umbraco which i 
        // can now use to traverse to display the product list
        // or lookup the product by sku
        if (string.IsNullOrEmpty(sku))
            //render the products list if no sku
            return RenderProductsList(model);
            return RenderProduct(model, sku);

I have this all working well in a side project of mine at the moment. This functionality will be exposed in an upcoming Umbraco version near you  :)

It’s also worth noting that all of this was accomplished outside of the Umbraco core with the publicly available APIs that currently exist. I will admit though there were a few hacks involved which of course won’t be hacks when moved into the core ;)

Multi targeting a single .Net project to build for different framework versions

May 2, 2014 04:18

Consider this scenario:

  • I have a project that relies on ASP.Net MVC and currently this project is built against the .Net framework 4.0 and MVC 4
  • I want to support MVC 5 for this project
  • To support MVC 5, I’d need to upgrade the project to use .Net framework 4.5
  • This would mean that developers still running .Net framework 4.0 would no longer be able to use my updated project

I also don’t want to have to create different projects and assemblies that target specific MVC versions (in this case you’d end up with assembly names like MyProject.MVC4.dll and MyProject.MVC5.dll). I have seen this done with other solutions and it works but I feel it is not necessary unless your project is using specific functionality from a particular MVC version.

In my case my project will compile perfectly against MVC 4 and 5 without any codebase changes so I’m not actually targeting against a specific MVC version ( >= 4 ). If your project uses specific functionality from the different MVC versions I think you will have to output different assemblies like MyProject.MVC5.dll. In that case this post will probably help:

The goal

The end result is that I want a single project file that has 4 build configurations:

  • Debug / Release
    • These will build against .Net 4.0
    • This will reference MVC 4
  • Debug-Net45 / Release-Net45
    • This will build against .Net 4.5
    • This will reference MVC 5

Each of these build configurations exports the same assembly name: MyProject.dll

I then want a single NuGet package which will install the correct DLL based on the .Net version that the user has installed.

How it’s done

Build configuration setup

To start with you’ll have a project that targets .Net framework 4.0 and references MVC 4 and 2 standard build configurations: Debug, Release.

First we need to create 2 new build configurations: Debug-Net45 and Release-Net45 and have these configurations output the DLLs to a custom folder. To do this we launch the Configuration Manager:


Create a new build configuration:


Enter the name of the new configuration and copy the configuration from it’s associated existing one. So Debug-Net45 would copy from Debug and Release-Net45 copies from Release.


Do this for both configurations – Debug-Net45 and Release-Net45.

Project setup

The next step requires manually editing your .csproj file since Visual Studio doesn’t want to normally allow you to do this. This is how you can configure each build type to target a different framework version. You’ll first need to find these 2 entries:

<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">

Inside each of these elements you need to explicitly tell these build configurations to use .Net framework 4.0 by adding this element:


Next you’ll want to copy/paste both of these property groups and:

  • Change the Condition to check for the new build configurations and to target .Net framework 4.5
  • Change the OutputPath to have a specific .Net 4.5 folder
  • Change the TargetFrameworkVersion to be .Net 4.5

You should end up with 2 new elements that look something like:

<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug-Net45|AnyCPU'">
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release-Net45|AnyCPU'">

Next we need to do this for the MVC references or any framework specific references you need to target. In this example it is just the MVC references and you’ll need to wrap them with an ItemGroup element, you’ll end up with something like this to target the MVC 4 libs:

<ItemGroup Condition=" '$(Configuration)'=='Debug' Or '$(Configuration)'=='Release'">
    <Reference Include="System.Web.Helpers, Version=, .....">
    <Reference Include="System.Web.Mvc, Version=, .....">
    <Reference Include="System.Web.Razor, Version=, .....">
    <Reference Include="System.Web.WebPages, Version=, .....">
    <Reference Include="System.Web.WebPages.Deployment, Version=, .....">
    <Reference Include="System.Web.WebPages.Razor, Version=, .....">

Then we need to go ahead and copy/paste this block but target the different build configurations and then swap out these MVC 4 version references with the MVC 5 version references.

Nuget package restore

For this tutorial I’m assuming you are using Nuget to reference your MVC libs and an easy way to get Nuget to play reasonably with this setup is to enable Nuget package restore for your solution – right click on your solution and click the button:


Then in your packages.config file you can manually add the MVC 5 references:

<?xml version="1.0" encoding="utf-8"?>
  <package id="Microsoft.AspNet.Mvc" 
           version="4.0.30506.0" targetFramework="net40" />
  <package id="Microsoft.AspNet.Razor" 
           version="2.0.30506.0" targetFramework="net40" />
  <package id="Microsoft.AspNet.WebPages" 
           version="2.0.30506.0" targetFramework="net40" />
  <package id="Microsoft.Web.Infrastructure" 
           version="" targetFramework="net40" />
  <package id="Microsoft.AspNet.Mvc" 
           version="5.0.0" targetFramework="net45" />
  <package id="Microsoft.AspNet.Razor" 
           version="3.0.0" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebPages" 
           version="3.0.0" targetFramework="net45" />

Now when you build your solution under the different build configurations Nuget will automatically go and get the correct MVC versions based on the current .Net Framework version.

Thats it!

With all of this in place it should ‘just work’ :) You will notice some odd looking icons in your references list in Visual Studio but it’s nothing to worry about, Visual Studio is just confused because it isn’t familiar with how you’ve tricked it!


So now when you build using your different build configurations, it will output the correct DLLs to the correct build folders:

  • Both Debug & Release will output to /bin/Debug & bin/Release with MVC 4 libraries and the MyProject.dll will be compiled against .Net Framework 4.0
  • Both Debug-Net45 & Release-Net45 will be output to /bin/Debug-Net45 & /bin/Release-Net45 with MVC 5 libraries and the MyProject.dll will be compiled against .Net Framework 4.5

And here’s some proof:



If you are using some automated build processes with MSBuild you can then just target the build configuration names you’d like to export.

The Nuget setup is pretty simple since you can target your dependencies by framework:

<group targetFramework="net40">
<!--between 4 and less than version 5-->
<dependency id="Microsoft.AspNet.Mvc" version="(4.0.20710,5)" />

<group targetFramework="net45">
<!--between 4 and less than version 6 (who knows what'll happen then)-->
<dependency id="Microsoft.AspNet.Mvc" version="(4.0.20710,6)" />

Then for each of your lib files in Nuget you ensure that you output them to the framework specific /lib folders such as:


This process has been implemented for the Client Dependency Framework version 1.8.0 to support MVC 4 and 5 without having to change the assembly name.

WebApi per controller configuration

March 21, 2014 00:56

This is more of a blog post about what not to do :)

At first glance, it would seem relatively painless to change your WebApi controller’s configuration, I’d assume most people would do what I initially did. Say for example you wanted to have your controller only support JSON, here’s what I initially tried (DO NOT DO THIS):

protected override void Initialize(HttpControllerContext controllerContext)
    var toRemove = controllerContext.Configuration.Formatters
        .Where(t => (t is JsonMediaTypeFormatter) == false).ToList();
    foreach (var r in toRemove)

Simple right, just override initialize in your controller and change the current controllerContext’s configuration…. WRONG :(

What this is actually doing is modifying the global WebApi configuration though it’s not clear that this is the case. Unfortunately the actual Configuration property on the controllerContext instance is assigned to the global one. I’m assuming the WebApi team has done this for a reason but I’m not sure what that is; as seen above it’s very easy to change the global WebApi configuration at runtime. Seems to me like it might have been a better idea to clone the global configuration instance and assign that to each HttpControllerContext object.

The correct way to specify per controller custom configuration in WebApi is to use the IControllerConfiguration interface. You can read all about here and it is fairly simple but it does seem like you have to jump through a few hoops for something that initially seems very straight forward.

Get JQuery requests to play nicely with AngularJS CSRF convention

December 6, 2013 19:06

Decided to write this quick post for anyone searching on this topic. AngularJS has it’s own convention for CSRF (Cross Site Request Forgery) protection but in some cases you’ll be calling these same server side services via JQuery so you might need to get JQuery requests to also follow Angular’s convention.

For information about Angular’s CSRF protection see the “Security Considerations” part of Angular’s $http documentation.

Luckily it’s pretty darn easy to get JQuery to follow this convention too and this will also work with 3rd party plugins that use JQuery for requests like Blueimp file uploader. The easiest way to get this done is to set the global JQuery $.ajax rules. Probably the best place to do this is in your Angular statement: ($cookies) {

    //This sets the default jquery ajax headers to include our csrf token, we
    // need to user the beforeSend method because the token might change 
    // (different for each logged in user)
        beforeSend: function (xhr) {
            xhr.setRequestHeader("X-XSRF-TOKEN", $cookies["XSRF-TOKEN"]);

That’s it!

It’s important to note to set the header using beforeSend, if you just set $.ajax options ‘headers’ section directly that means the header cannot be dynamic – which you’ll probably want if you have users logging in/out.

How to inspect assemblies with reflection before including them in your application

October 25, 2013 22:13

If you application supports plugins or extensions in some cases it might be useful to scan a packages assemblies before importing them in to your app. Some reasons for this might be:

  • Checking if the package has missing assembly references
  • Checking if the assembly references obsolete types that might make the package unstable
  • Checking the .Net targeted framework of the assembly
  • Any other assembly inspection to determine it is compatible with your app

To do this you can load assemblies using Assembly.ReflectionOnlyLoadFrom and Assembly.ReflectionOnlyLoad methods which load assemblies into a special assembly load context called “reflection-only context” which will safely let you inspect these assemblies.

Further reading:

A great article on Reflection Only Assembly Loading and if you want to know more about assembly load contexts, here’s an explanation.

Loading in assemblies

For this example, we’ll assume that all of the assemblies for a package are in some folder outside of the normal /bin folder (not loaded in to the current app) and each assembly for the package will need to be inspected for type references that are not supported.

A common mistake when loading in assemblies with reflection (especially in the LoadFrom context) is to load them in one at a time, whereas they generally will need to be all loaded in before inspecting them since they probably have references to each other. Another thing that generally must be done is adding an event listener on AppDomain.ReflectionOnlyAssemblyResolve because even though all known referenced assemblies are loading into the context some assemblies might not be explicitly referenced but are need to load the assembly. This handler provides a way to resolve those missing references.

The first thing to do is setup the event handler

AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += (s, e) =>
    var a = Assembly.ReflectionOnlyLoad(e.Name);
    if (a == null) throw new TypeLoadException("Could not load assembly " + e.Name);
    return a;

Next we need to load all of the assembly files in the folder

foreach (var f in files) Assembly.ReflectionOnlyLoadFrom(f);

Then load all of their referenced assemblies in to the reflection context

//Then load each referenced assembly into the context
var assembliesWithErrors = new List<string>();
foreach (var f in files)
    var reflectedAssembly = Assembly.ReflectionOnlyLoadFrom(f);
    foreach (var assemblyName in reflectedAssembly.GetReferencedAssemblies())
        catch (FileNotFoundException)
            //if an exception occurs it means that a referenced assembly could not be found                        
                string.Concat("This package references the assembly '",
                    "' which was not found, this package may have problems running"));

In the catch, I’m detecting assembly reference errors and adding an error message to the outgoing method response and also adding that assembly to the assembliesWithErrors list which is used later to ensure we’re not inspecting assemblies that couldn’t be loaded.

Now that all the assemblies are loaded we can inspect them (ignoring ones with errors). This example is looking for any assemblies that have types implementing ‘MyType’. If they do implement this type, add the assembly to a list to return from the current method.

//now that we have all referenced types into the context we can look up stuff
foreach (var f in files.Except(assembliesWithErrors))
    //now we need to see if they contain any type 'MyType'
    var reflectedAssembly = Assembly.ReflectionOnlyLoadFrom(f);
    var found = reflectedAssembly.GetExportedTypes()
    if (found.Any())

Separate AppDomain

It’s best to execute all of this logic in a separate AppDomain because once assemblies are loaded in to a context, they cannot be unloaded and since we are loading in from files, those files will remain locked until the AppDomain is shutdown. Explaining how to create a separate AppDomain is outside the scope of this article but the code is included in the source below.

Source Code

Here’s a class the encapsulates all of this logic and of course if you can do much more when inspecting assemblies for various types.