<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="https://shazwazza.com/rss/xslt"?>
<rss xmlns:a10="http://www.w3.org/2005/Atom" version="2.0">
  <channel>
    <title>Shazwazza</title>
    <link>https://shazwazza.com/</link>
    <description>My blog which is pretty much just all about coding</description>
    <generator>Articulate, blogging built on Umbraco</generator>
    <image>
      <url>/media/0libq25y/frog.png?rmode=max&amp;v=1da0e911f4e6890</url>
      <title>Shazwazza</title>
      <link>https://shazwazza.com/</link>
    </image>
    <item>
      <guid isPermaLink="false">1328</guid>
      <link>https://shazwazza.com/post/custom-assembly-loading-with-aspnet-core/</link>
      <category>ASP.Net</category>
      <title>Custom Assembly loading with Asp.Net Core</title>
      <description>&lt;p&gt;Building a plugin system in Asp.Net Core is a dream compared to previous Asp.Net versions! &lt;/p&gt; &lt;p&gt;In previous versions it was not really feasible to load Assemblies located outside of the /bin folder &lt;em&gt;&lt;u&gt;for a web application&lt;/u&gt;&lt;/em&gt;. &lt;a href="http://shazwazza.com/post/developing-a-plugin-framework-in-aspnet-with-medium-trust/" target="_blank"&gt;I battled with this concept quite a long time ago&lt;/a&gt; and although it’s sort of possible, the notion of having a plugin system that supported loading DLLs from outside of the /bin folder was riddled with hacks/problems and not really supported OOTB. &lt;/p&gt; &lt;p&gt;A large part of the issues has to do with something called an ‘Assembly Load Context’. In traditional .Net there are 3 of these context types: “&lt;strong&gt;Load&lt;/strong&gt;”, “&lt;strong&gt;LoadFrom&lt;/strong&gt;” and “&lt;strong&gt;Neither&lt;/strong&gt;”, &lt;a href="http://blogs.msdn.com/b/suzcook/archive/2003/05/29/57143.aspx" target="_blank"&gt;here’s a very old but very relevant post about these contexts&lt;/a&gt; from Suzanne Cook. In traditional Asp.Net, the “Load” context is used as the default context and it is managed by something called &lt;em&gt;Fusion&lt;/em&gt; (.Net’s normal Assembly Loader/Binder). The problem with this context is that it is difficult to load an assembly into it that isn’t located in &lt;em&gt;Fusion’s &lt;/em&gt;probing paths (i.e. /bin folder). If you load in an Assembly with a different Assembly Load Context and then try to mix it’s Types with the Types from the default context&amp;nbsp; … you’ll quickly see that it’s not going to work. &lt;/p&gt; &lt;h2&gt;The “Neither” context&lt;/h2&gt; &lt;p&gt;Here is the Neither context definition as defined by Suzanne Cook:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;em&gt;If the user generated or found the assembly instead of Fusion, it's in neither context. This applies to assemblies loaded by Assembly.Load(byte[]) and Reflection Emit assemblies (that haven't been loaded from disk). &lt;/em&gt;&lt;a href="http://blogs.msdn.com/suzcook/archive/2003/09/19/57248.aspx"&gt;&lt;em&gt;Assembly.LoadFile()&lt;/em&gt;&lt;/a&gt;&lt;em&gt; assemblies are also generally loaded into this context, even though a path is given (because it doesn't go through Fusion).&lt;/em&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;In Asp.Net Core (targeting CoreCLR), the default Assembly Load Context is the “Neither” context. This is a flexible context because it doesn’t use &lt;em&gt;Fusion&lt;/em&gt; and&amp;nbsp; it allows for loading assemblies any way that you want - including loading an assembly from a byte array, from a path or by a name. Since all of Asp.Net Core uses this context it means that all of the types loaded in with this context can talk to each other without having the previous Asp.Net problems.&lt;/p&gt; &lt;p&gt;I would assume that Asp.Net Core targeting Desktop CLR would still operate the same as before and still have the 3 types of Assembly Load Context’s … Maybe someone over at Microsoft can elaborate on that one? (David Fowler… surely you know? :)&lt;/p&gt; &lt;h2&gt;Finding referenced plugin assemblies&lt;/h2&gt; &lt;p&gt;In many cases if you create a product that supports plugin types, developers will create plugins for your product and ship them via Nuget. This is a pretty standard approach since it allows developers that are using your product to install plugins from the Nuget command line or from within Visual Studio. In this case plugin types will be found in referenced assemblies to your application and will be automatically loaded. Asp.Net Core has an interface called &lt;em&gt;Microsoft.Extensions.PlatformAbstractions.ILibraryManager&lt;/em&gt; that can be used to resolve your application’s currently referenced ‘Libraries’ (i.e Nuget packages) and then each ‘Library’ returned exposes the Assemblies that it includes. Asp.Net MVC 6 has an even more helpful interface called &lt;em&gt;Microsoft.AspNet.Mvc.Infrastructure.IAssemblyProvider&lt;/em&gt; which returns a list of referenced assemblies that are filtered based on if they are assemblies that reference a subset of MVC assemblies. The default implementation of &lt;em&gt;IAssemblyProvider&lt;/em&gt; (&lt;em&gt;DefaultAssemblyProvider&lt;/em&gt;) is extensible and we can use it to override it’s property &lt;em&gt;ReferenceAssemblies&lt;/em&gt; in order to supply our own product assembly names instead of the MVC ones. This is perfect since this allows us to get a list of candidate assemblies that might contain plugins for your product:&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; ReferencePluginAssemblyProvider : DefaultAssemblyProvider
{
    &lt;span class="rem"&gt;//NOTE: The DefaultAssemblyProvider uses ILibraryManager to do the library/assembly querying&lt;/span&gt;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; ReferencePluginAssemblyProvider(ILibraryManager libraryManager) : &lt;span class="kwrd"&gt;base&lt;/span&gt;(libraryManager)
    {
    }

    &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; HashSet&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt; ReferenceAssemblies 
        =&amp;gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; HashSet&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;(&lt;span class="kwrd"&gt;new&lt;/span&gt;[] {&lt;span class="str"&gt;"MyProduct.Web"&lt;/span&gt;, &lt;span class="str"&gt;"MyProduct.Core"&lt;/span&gt;});
}&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;p&gt;now if you want to get a list of candidate assemblies that your application is referencing you could do:&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="rem"&gt;//returns all assemblies that reference your product Assemblies&lt;/span&gt;
var candidateReferenceAssemblies = referencedPluginAssemblyProvider.CandidateAssemblies;&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;h2&gt;Finding and loading non-referenced plugin assemblies&lt;/h2&gt;
&lt;p&gt;This is where things get fun since this is the type of thing that wasn’t really very feasible with traditional Asp.Net web apps. Lets say you have a plugin framework where a plugin is installed via your web app, not in Visual Studio and therefore not directly referenced in your project. For this example, the plugin is a self contained collection of files and folders which could consist of: Css, JavaScript, Razor Views, and Assemblies. This plugin model is pretty nice since to install the plugin would mean just dropping the plugin folder into the right directory in your app and similarly&amp;nbsp; to uninstall it you can just remove the folder.&amp;nbsp; The first step is to be able to load in these plugin Assemblies from custom locations. For an example, let’s assume the web app has the following folder structure:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;App Root 
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;App_Plugins &lt;/strong&gt;&lt;em&gt;&amp;lt;—This will be the directory that contains plugin folders&lt;/em&gt; 
&lt;ul&gt;
&lt;li&gt;MyPlugin1 
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;bin &lt;/strong&gt;&lt;em&gt;&amp;lt;—by convention we’ll search for Assemblies in the /bin folder inside of a plugin&lt;/em&gt; 
&lt;li&gt;Views&lt;/li&gt;&lt;/ul&gt;
&lt;li&gt;MyPlugin2 
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;bin&lt;em&gt; &lt;/em&gt;&lt;/strong&gt;&lt;em&gt;&amp;lt;—by convention we’ll search for Assemblies in the /bin folder inside of a plugin&lt;/em&gt; 
&lt;li&gt;css&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;li&gt;Views 
&lt;li&gt;&lt;em&gt;wwwroot&lt;/em&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;h3&gt;IAssemblyLoader&lt;/h3&gt;
&lt;p&gt;The first thing we need is an ‘&lt;em&gt;Microsoft.Extensions.PlatformAbstractions.IAssemblyLoader&lt;/em&gt;’, this is the thing that will do the assembly loading into the Assembly Load Context based on an &lt;em&gt;AssemblyName &lt;/em&gt;and a location of a DLL:&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; DirectoryLoader : IAssemblyLoader
{
    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;readonly&lt;/span&gt; IAssemblyLoadContext _context;
    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;readonly&lt;/span&gt; DirectoryInfo _path;

    &lt;span class="kwrd"&gt;public&lt;/span&gt; DirectoryLoader(DirectoryInfo path, IAssemblyLoadContext context)
    {
        _path = path;
        _context = context;
    }

    &lt;span class="kwrd"&gt;public&lt;/span&gt; Assembly Load(AssemblyName assemblyName)
    {
        &lt;span class="kwrd"&gt;return&lt;/span&gt; _context.LoadFile(Path.Combine(_path.FullName, assemblyName.Name + &lt;span class="str"&gt;".dll"&lt;/span&gt;));
    }

    &lt;span class="kwrd"&gt;public&lt;/span&gt; IntPtr LoadUnmanagedLibrary(&lt;span class="kwrd"&gt;string&lt;/span&gt; name)
    {
        &lt;span class="rem"&gt;//this isn't going to load any unmanaged libraries, just throw&lt;/span&gt;
        &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; NotImplementedException();
    }
}&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;h3&gt;IAssemblyProvider&lt;/h3&gt;
&lt;p&gt;Next up we’ll need a custom &lt;em&gt;IAssemblyProvider&lt;/em&gt; but instead of using the one MVC ships with, this one will be totally custom in order to load and resolve the assemblies based on the plugin’s /bin folders. The following code should be pretty straight forward, the &lt;em&gt;CandidateAssemblies&lt;/em&gt; property iterates over each found /bin folder inside of a plugin’s folder inside of App_Plugins. For each /bin folder found it creates a &lt;em&gt;DirectoryLoader &lt;/em&gt;mentioned above and loads in each DLL found by it’s &lt;em&gt;AssemblyName&lt;/em&gt; into the current Assembly Load Context.&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;span class="rem"&gt;/// This will return assemblies found in App_Plugins plugin's /bin folders&lt;/span&gt;
&lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; CustomDirectoryAssemblyProvider : IAssemblyProvider
{
    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;readonly&lt;/span&gt; IFileProvider _fileProvider;
    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;readonly&lt;/span&gt; IAssemblyLoadContextAccessor _loadContextAccessor;
    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;readonly&lt;/span&gt; IAssemblyLoaderContainer _assemblyLoaderContainer;

    &lt;span class="kwrd"&gt;public&lt;/span&gt; CustomDirectoryAssemblyProvider(
            IFileProvider fileProvider, 
            IAssemblyLoadContextAccessor loadContextAccessor, 
            IAssemblyLoaderContainer assemblyLoaderContainer)
    {
        _fileProvider = fileProvider;
        _loadContextAccessor = loadContextAccessor;
        _assemblyLoaderContainer = assemblyLoaderContainer;
    }

    &lt;span class="kwrd"&gt;public&lt;/span&gt; IEnumerable&amp;lt;Assembly&amp;gt; CandidateAssemblies
    {
        get
        {
            var content = _fileProvider.GetDirectoryContents(&lt;span class="str"&gt;"/App_Plugins"&lt;/span&gt;);
            &lt;span class="kwrd"&gt;if&lt;/span&gt; (!content.Exists) &lt;span class="kwrd"&gt;yield&lt;/span&gt; &lt;span class="kwrd"&gt;break&lt;/span&gt;;
            &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (var pluginDir &lt;span class="kwrd"&gt;in&lt;/span&gt; content.Where(x =&amp;gt; x.IsDirectory))
            {
                var binDir = &lt;span class="kwrd"&gt;new&lt;/span&gt; DirectoryInfo(Path.Combine(pluginDir.PhysicalPath, &lt;span class="str"&gt;"bin"&lt;/span&gt;));
                &lt;span class="kwrd"&gt;if&lt;/span&gt; (!binDir.Exists) &lt;span class="kwrd"&gt;continue&lt;/span&gt;;
                &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (var assembly &lt;span class="kwrd"&gt;in&lt;/span&gt; GetAssembliesInFolder(binDir))
                {
                    &lt;span class="kwrd"&gt;yield&lt;/span&gt; &lt;span class="kwrd"&gt;return&lt;/span&gt; assembly;
                }
            }
        }
    }

    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
    &lt;span class="rem"&gt;/// Returns assemblies loaded from /bin folders inside of App_Plugins&lt;/span&gt;
    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
    &lt;span class="rem"&gt;/// &amp;lt;param name="binPath"&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;
    &lt;span class="rem"&gt;/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;private&lt;/span&gt; IEnumerable&amp;lt;Assembly&amp;gt; GetAssembliesInFolder(DirectoryInfo binPath)
    {
        &lt;span class="rem"&gt;// Use the default load context&lt;/span&gt;
        var loadContext = _loadContextAccessor.Default;

        &lt;span class="rem"&gt;// Add the loader to the container so that any call to Assembly.Load &lt;/span&gt;
        &lt;span class="rem"&gt;// will call the load context back (if it's not already loaded)&lt;/span&gt;
        &lt;span class="kwrd"&gt;using&lt;/span&gt; (_assemblyLoaderContainer.AddLoader(
            &lt;span class="kwrd"&gt;new&lt;/span&gt; DirectoryLoader(binPath, loadContext)))
        {
            &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (var fileSystemInfo &lt;span class="kwrd"&gt;in&lt;/span&gt; binPath.GetFileSystemInfos(&lt;span class="str"&gt;"*.dll"&lt;/span&gt;))
            {
                &lt;span class="rem"&gt;//// In theory you should be able to use Assembly.Load() here instead&lt;/span&gt;
                &lt;span class="rem"&gt;//var assembly1 = Assembly.Load(AssemblyName.GetAssemblyName(fileSystemInfo.FullName));&lt;/span&gt;
                var assembly2 = loadContext.Load(AssemblyName.GetAssemblyName(fileSystemInfo.FullName));
                &lt;span class="kwrd"&gt;yield&lt;/span&gt; &lt;span class="kwrd"&gt;return&lt;/span&gt; assembly2;
            }
        }
    }
}&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;p&gt;That’s pretty much it! If you have an instance of &lt;em&gt;CustomDirectoryAssemblyProvider&lt;/em&gt; then you can get Assembly references to all of the assemblies found in App_Plugins:&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="rem"&gt;//returns all plugin assemblies found in App_Plugins&lt;/span&gt;
var candidatePluginAssemblies = customDirectoryAssemblyProvider.CandidateAssemblies;&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;h2&gt;Integrating non-referenced plugins/Assemblies with MVC&lt;/h2&gt;
&lt;p&gt;What if you had custom plugin types as MVC Controllers or other MVC types? By default MVC only knows about assemblies that your project has references to based on the &lt;em&gt;DefaultAssemblyLoader&lt;/em&gt;.&amp;nbsp; If we wanted MVC to know about Controllers that exist in a plugin not referenced by your project (i.e. in App_Plugins) then it’s a case of registering a custom &lt;em&gt;IAssemblyProvider&lt;/em&gt; in IoC which will get resolved by MVC. To make this super flexible we can create a custom &lt;em&gt;IAssemblyProvider&lt;/em&gt; that wraps multiple other ones and allows you to pass in a custom &lt;em&gt;referenceAssemblies&lt;/em&gt; filter if you wanted to use this to resolve your own plugin types:&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; CompositeAssemblyProvider : DefaultAssemblyProvider
{
    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;readonly&lt;/span&gt; IAssemblyProvider[] _additionalProviders;
    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;readonly&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt;[] _referenceAssemblies;

    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
    &lt;span class="rem"&gt;/// Constructor&lt;/span&gt;
    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
    &lt;span class="rem"&gt;/// &amp;lt;param name="libraryManager"&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;
    &lt;span class="rem"&gt;/// &amp;lt;param name="additionalProviders"&amp;gt;&lt;/span&gt;
    &lt;span class="rem"&gt;/// If passed in will concat the assemblies returned from these &lt;/span&gt;
    &lt;span class="rem"&gt;/// providers with the default assemblies referenced&lt;/span&gt;
    &lt;span class="rem"&gt;/// &amp;lt;/param&amp;gt;&lt;/span&gt;
    &lt;span class="rem"&gt;/// &amp;lt;param name="referenceAssemblies"&amp;gt;&lt;/span&gt;
    &lt;span class="rem"&gt;/// If passed in it will filter the candidate libraries to ones&lt;/span&gt;
    &lt;span class="rem"&gt;/// that reference the assembly names passed in. &lt;/span&gt;
    &lt;span class="rem"&gt;/// (i.e. "MyProduct.Web", "MyProduct.Core" )&lt;/span&gt;
    &lt;span class="rem"&gt;/// &amp;lt;/param&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; CompositeAssemblyProvider(
        ILibraryManager libraryManager,
        IAssemblyProvider[] additionalProviders = &lt;span class="kwrd"&gt;null&lt;/span&gt;,
        &lt;span class="kwrd"&gt;string&lt;/span&gt;[] referenceAssemblies = &lt;span class="kwrd"&gt;null&lt;/span&gt;) : &lt;span class="kwrd"&gt;base&lt;/span&gt;(libraryManager)
    {
        _additionalProviders = additionalProviders;
        _referenceAssemblies = referenceAssemblies;
    }

    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
    &lt;span class="rem"&gt;/// Uses the default filter if a custom list of reference&lt;/span&gt;
    &lt;span class="rem"&gt;/// assemblies has not been provided&lt;/span&gt;
    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; HashSet&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt; ReferenceAssemblies
        =&amp;gt; _referenceAssemblies == &lt;span class="kwrd"&gt;null&lt;/span&gt;
            ? &lt;span class="kwrd"&gt;base&lt;/span&gt;.ReferenceAssemblies
            : &lt;span class="kwrd"&gt;new&lt;/span&gt; HashSet&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;(_referenceAssemblies);
    
    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
    &lt;span class="rem"&gt;/// Returns the base Libraries referenced along with any DLLs/Libraries&lt;/span&gt;
    &lt;span class="rem"&gt;/// returned from the custom IAssemblyProvider passed in&lt;/span&gt;
    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
    &lt;span class="rem"&gt;/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; IEnumerable&amp;lt;Library&amp;gt; GetCandidateLibraries()
    {
        var baseCandidates = &lt;span class="kwrd"&gt;base&lt;/span&gt;.GetCandidateLibraries();
        &lt;span class="kwrd"&gt;if&lt;/span&gt; (_additionalProviders == &lt;span class="kwrd"&gt;null&lt;/span&gt;) &lt;span class="kwrd"&gt;return&lt;/span&gt; baseCandidates;
        &lt;span class="kwrd"&gt;return&lt;/span&gt; baseCandidates               
            .Concat(
            _additionalProviders.SelectMany(provider =&amp;gt; provider.CandidateAssemblies.Select(
                x =&amp;gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; Library(x.FullName, &lt;span class="kwrd"&gt;null&lt;/span&gt;, Path.GetDirectoryName(x.Location), &lt;span class="kwrd"&gt;null&lt;/span&gt;, Enumerable.Empty&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;(),
                    &lt;span class="kwrd"&gt;new&lt;/span&gt;[] { &lt;span class="kwrd"&gt;new&lt;/span&gt; AssemblyName(x.FullName) }))));
    }
}&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;p&gt;To register this in IoC you just need to make sure it’s registered after you register MVC so that it overrides the last registered &lt;em&gt;IAssemblyProvider&lt;/em&gt;:&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="rem"&gt;//Add MVC services&lt;/span&gt;
services.AddMvc();
&lt;span class="rem"&gt;//Replace the default IAssemblyProvider with the composite one&lt;/span&gt;
services.AddSingleton&amp;lt;IAssemblyProvider, CompositeAssemblyProvider&amp;gt;(provider =&amp;gt;
{
    &lt;span class="rem"&gt;//create the custom plugin directory provider&lt;/span&gt;
    var hosting = provider.GetRequiredService&amp;lt;IApplicationEnvironment&amp;gt;();
    var fileProvider = &lt;span class="kwrd"&gt;new&lt;/span&gt; PhysicalFileProvider(hosting.ApplicationBasePath);
    var pluginAssemblyProvider = &lt;span class="kwrd"&gt;new&lt;/span&gt; CustomDirectoryAssemblyProvider(
        fileProvider,         
        PlatformServices.Default.AssemblyLoadContextAccessor,
        PlatformServices.Default.AssemblyLoaderContainer);
    &lt;span class="rem"&gt;//return the composite one - this wraps the default MVC one&lt;/span&gt;
    &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; CompositeAssemblyProvider(
        provider.GetRequiredService&amp;lt;ILibraryManager&amp;gt;(),
        &lt;span class="kwrd"&gt;new&lt;/span&gt; IAssemblyProvider[] {pluginAssemblyProvider});
});&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Your all set! Now you have the ability to load in Assemblies from any location you want, you could even load them in as byte array’s from an external data source.&amp;nbsp; What’s great about all of this is that it just works and you can integrate these external Assemblies into MVC. &lt;/p&gt;
&lt;p&gt;Some things worth noting:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Parts of the assembly loading APIs are changing a bit in Asp.Net Core RC2: &lt;a title="https://github.com/aspnet/Announcements/issues/149" href="https://github.com/aspnet/Announcements/issues/149"&gt;https://github.com/aspnet/Announcements/issues/149&lt;/a&gt; 
&lt;li&gt;The above code doesn’t take into account what happens if you load in the same Assembly from multiple locations. In this case, the last one in wins/is active AFAIK – I haven’t tested this yet but I’m pretty sure that’s how it works. 
&lt;li&gt;You may have some issues if load in the same Assembly more than once from multiple locations if those Assemblies have different strong names, or major versions applied to them – I also haven’t tested this yet&lt;/li&gt;&lt;/ul&gt;</description>
      <pubDate>Thu, 23 Mar 2023 15:08:15 Z</pubDate>
      <a10:updated>2023-03-23T15:08:15Z</a10:updated>
    </item>
    <item>
      <guid isPermaLink="false">1221</guid>
      <link>https://shazwazza.com/post/developing-a-plugin-framework-in-aspnet-mvc-with-medium-trust/</link>
      <category>ASP.Net</category>
      <category>Umbraco</category>
      <title>Developing a plugin framework in ASP.NET MVC with medium trust</title>
      <description>&lt;p&gt;I’ve recently spent quite a lot of time researching and prototyping different ways to create a plugin engine in ASP.NET MVC3 and primarily finding a nice way to load plugins (DLLs) in from outside of the ‘bin’ folder. Although this post focuses on MVC3, I am sure that the same principles will apply for other MVC versions. &lt;/p&gt; &lt;h1&gt;The Issues&lt;/h1&gt; &lt;p&gt;Loading DLLs from outside of the ‘bin’ folder isn’t really anything new or cutting edge, however when working with MVC this becomes more difficult. This is primarily due to how MVC loads/finds types that it needs to process including controllers, view models (more precisely the generic argument passed to a &lt;a href="http://www.google.com.au/url?sa=t&amp;amp;source=web&amp;amp;cd=1&amp;amp;ved=0CBkQFjAA&amp;amp;url=http%3A%2F%2Fmsdn.microsoft.com%2Fes-es%2Flibrary%2Fdd470798.aspx&amp;amp;rct=j&amp;amp;q=ViewPage%20msdn&amp;amp;ei=BLAmTd_lPIeycfL36ZgB&amp;amp;usg=AFQjCNFTkQSor1HJFAMkHw0h3BUiiIuEzg&amp;amp;cad=rja" target="_blank"&gt;ViewPage&lt;/a&gt; or used with the @model declaration in Razor), model binders, etc… MVC is very tied to the &lt;a href="http://www.google.com.au/url?sa=t&amp;amp;source=web&amp;amp;cd=1&amp;amp;ved=0CBUQFjAA&amp;amp;url=http%3A%2F%2Fmsdn.microsoft.com%2Fen-us%2Flibrary%2Fsystem.web.compilation.buildmanager.aspx&amp;amp;rct=j&amp;amp;q=BuildManager%20msdn%20asp.net&amp;amp;ei=5LAmTa6nFsn4cbKezYEB&amp;amp;usg=AFQjCNH96gOQZt36Kjh-lIs5CKmWEtPjCA&amp;amp;cad=rja" target="_blank"&gt;BuildManager&lt;/a&gt; which is the mechanism for compiling views, and locating other services such as controllers. By default the BuildManager is only familiar with assembies in the ‘bin’ folder and in the GAC, so if you start putting DLLs in folders outside of the ‘bin’ then it won’t be able to locate the MVC services and objects that you might want it to be referencing.&lt;/p&gt; &lt;p&gt;Another issue that needs to be dealt with is DLL file locking. When a plugin DLL is loaded and is in use the CLR will lock the file. This becomes an an issue if developers want to update the plugin DLL while the website is running since they won’t be able to unless they bump the web.config or take the site down. This holds true for &lt;a href="http://msdn.microsoft.com/en-us/library/dd460648.aspx" target="_blank"&gt;MEF&lt;/a&gt; and how it loads DLLs as well.&lt;/p&gt; &lt;h1&gt;.Net 4 to the rescue… almost&lt;/h1&gt; &lt;p&gt;One of the new features in .Net 4 is the ability to execute code before the app initializes which compliments another new feature of the BuildManager that lets you add assembly references to it at runtime (which must be done on application pre-init). Here’s a nice little reference to these new features from Phil Haack: &lt;a title="http://haacked.com/archive/2010/05/16/three-hidden-extensibility-gems-in-asp-net-4.aspx" href="http://haacked.com/archive/2010/05/16/three-hidden-extensibility-gems-in-asp-net-4.aspx"&gt;http://haacked.com/archive/2010/05/16/three-hidden-extensibility-gems-in-asp-net-4.aspx&lt;/a&gt;.&amp;nbsp; This is essential to making a plugin framework work with MVC so that the BuildManager knows where to reference your plugin DLLs outside of the ‘bin’. However, this isn’t the end of the story. &lt;/p&gt; &lt;h2&gt;Strongly typed Views with model Types located in plugin DLLs&lt;/h2&gt; &lt;p&gt;Unfortunately if you have a view that is strongly typed to a model that exists outside of the ‘bin’, then you’ll find out very quickly that it doesn’t work and it won’t actually tell you why. This is because the &lt;a href="http://weblogs.asp.net/scottgu/archive/2010/07/02/introducing-razor.aspx" target="_blank"&gt;RazorViewEngine&lt;/a&gt;&amp;nbsp; uses the BuildManager to compile the view into a dynamic assembly but then uses &lt;em&gt;Activator.CreateInstance&lt;/em&gt; to instantiate the newly compiled object. This is where the problem lies, the current AppDomain doesn’t know how to resolve the model Type for the strongly typed view since it doesn’t exist in the ‘bin’ or GAC.&amp;nbsp; An even worse part about this scenario is that you don’t get any error message telling you why this isn’t working, or where the problem is. Instead you get the nice MVC view not found error: “…&lt;i&gt;or its master was not found or no view engine supports the searched locations. The following locations were searched: ….”&lt;/i&gt; telling you that it has searched for views in all of the ViewEngine locations and couldn’t find it… which is actually not the error at all.&amp;nbsp; Deep in the MVC3 source, it tries to instantiate the view object from the dynamic assembly and it fails so it just keeps looking for that view in the rest of the ViewEngine paths.&lt;/p&gt; &lt;p&gt;&lt;em&gt;NOTE: Even though in MVC3 there’s a new &lt;a href="http://bradwilson.typepad.com/blog/2010/10/service-location-pt11-view-page-activator.html" target="_blank"&gt;IViewPageActivator&lt;/a&gt; which should be responsible for instantiating the views that have been compiled with the BuildManager, implementing a custom IViewPageActivator to handle this still does not work because somewhere in the MVC3 codebase fails before the call to the IViewPageActivator which has to do with resolving an Assembly that is not in the ‘bin’. &lt;/em&gt;&lt;/p&gt; &lt;h1&gt;Full trust&lt;/h1&gt; &lt;p&gt;When working in &lt;a href="http://msdn.microsoft.com/en-us/library/wyts434y.aspx" target="_blank"&gt;Full Trust&lt;/a&gt; we have a few options for dealing with the above scenario:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Use the AppDomain’s &lt;a href="http://msdn.microsoft.com/en-us/library/system.appdomain.assemblyresolve.aspx" target="_blank"&gt;ResolveAssembly&lt;/a&gt; event  &lt;ul&gt; &lt;li&gt;By subscribing to this event, you are able to instruct the AppDomain where to look when it can’t find a reference to a Type.  &lt;li&gt;This is easily done by checking if your plugin assemblies match the assembly being searched for, and then returning the Assembly object if found: &lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt; &lt;div id="scid:9D7513F9-C04C-4721-824A-2B34F0212519:1991111b-18f6-447d-b453-b6a3a4f22a0b" class="wlWriterSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"&gt;&lt;pre style="overflow: auto; height: 152px; width: 680px; background-color: white"&gt;&lt;div&gt;&lt;!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--&gt;&lt;span style="color: #0000ff"&gt;static&lt;/span&gt;&lt;span style="color: #000000"&gt; Assembly CurrentDomain_AssemblyResolve(&lt;/span&gt;&lt;span style="color: #0000ff"&gt;object&lt;/span&gt;&lt;span style="color: #000000"&gt; sender, ResolveEventArgs args)
{
    var pluginsFolder &lt;/span&gt;&lt;span style="color: #000000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #0000ff"&gt;new&lt;/span&gt;&lt;span style="color: #000000"&gt; DirectoryInfo(HostingEnvironment.MapPath(&lt;/span&gt;&lt;span style="color: #800000"&gt;"&lt;/span&gt;&lt;span style="color: #800000"&gt;~/Plugins&lt;/span&gt;&lt;span style="color: #800000"&gt;"&lt;/span&gt;&lt;span style="color: #000000"&gt;));
    &lt;/span&gt;&lt;span style="color: #0000ff"&gt;return&lt;/span&gt;&lt;span style="color: #000000"&gt; (from f &lt;/span&gt;&lt;span style="color: #0000ff"&gt;in&lt;/span&gt;&lt;span style="color: #000000"&gt; pluginsFolder.GetFiles(&lt;/span&gt;&lt;span style="color: #800000"&gt;"&lt;/span&gt;&lt;span style="color: #800000"&gt;*.dll&lt;/span&gt;&lt;span style="color: #800000"&gt;"&lt;/span&gt;&lt;span style="color: #000000"&gt;, SearchOption.AllDirectories)
            let assemblyName &lt;/span&gt;&lt;span style="color: #000000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; AssemblyName.GetAssemblyName(f.FullName)
            &lt;/span&gt;&lt;span style="color: #0000ff"&gt;where&lt;/span&gt;&lt;span style="color: #000000"&gt; assemblyName.FullName &lt;/span&gt;&lt;span style="color: #000000"&gt;==&lt;/span&gt;&lt;span style="color: #000000"&gt; args.Name &lt;/span&gt;&lt;span style="color: #000000"&gt;||&lt;/span&gt;&lt;span style="color: #000000"&gt; assemblyName.FullName.Split(&lt;/span&gt;&lt;span style="color: #800000"&gt;'&lt;/span&gt;&lt;span style="color: #800000"&gt;,&lt;/span&gt;&lt;span style="color: #800000"&gt;'&lt;/span&gt;&lt;span style="color: #000000"&gt;)[&lt;/span&gt;&lt;span style="color: #800080"&gt;0&lt;/span&gt;&lt;span style="color: #000000"&gt;] &lt;/span&gt;&lt;span style="color: #000000"&gt;==&lt;/span&gt;&lt;span style="color: #000000"&gt; args.Name
            select Assembly.LoadFile(f.FullName)).FirstOrDefault();
}&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Shadow copy your plugin DLLs into the AppDomain’s &lt;a href="http://msdn.microsoft.com/en-us/library/system.appdomain.dynamicdirectory.aspx" target="_blank"&gt;DynamicDirectory&lt;/a&gt;. 
&lt;ul&gt;
&lt;li&gt;This is the directory that the BuildManager compiles it’s dynamic assemblies into and is also a directory that the AppDomain looks to when resolving Type’s from Assemblies. 
&lt;li&gt;You can shadow copy your plugin DLLs to this folder on app pre-init and everything ‘should just work’ &lt;/li&gt;&lt;/ul&gt;
&lt;li&gt;Replace the RazorViewEngine with a custom razor view engine that compiles views manually but makes references to the appropriate plugin DLLs 
&lt;ul&gt;
&lt;li&gt;I actually had this working in an &lt;a href="http://umbraco.org" target="_blank"&gt;Umbraco&lt;/a&gt; v5 prototype but it is hugely overkill and unnecessary plus you actually would have to replace the RazorViewEngine which is pretty absurd. &lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;h1&gt;The burden of Medium Trust&lt;/h1&gt;
&lt;p&gt;In the MVC world there’s only a couple hurdles to jump when loading in plugins from outside of the ‘bin’ folder in Full Trust. In Medium Trust however, things get interesting. Unfortunately in Medium Trust it is not possible to handle the AssemblyResolve event and it’s also not possible to access the DynamicDirectory of the AppDomain so the above two solutions get thrown out the window. Further to this it seems as though you can’t use CodeDom in Medium Trust to custom compile views.&lt;/p&gt;
&lt;h2&gt;Previous attempts&lt;/h2&gt;
&lt;p&gt;For a while I began to think that this wasn’t possible and I thought I tried everything:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Shadow copying DLLs from the plugins folder into the ‘bin’ folder on application pre-init 
&lt;ul&gt;
&lt;li&gt;This fails because even during app pre-init, the application pool will still recycle. Well, it doesn’t actually ‘fail’ unless you keep re-copying the DLL into the bin. If you check if it already exists and don’t copy into the bin than this solution will work for you but it’s hardly a ‘solution’ since you might as well just put all your DLLs into the ‘bin’ in the first place. &lt;/li&gt;&lt;/ul&gt;
&lt;li&gt;Trying to use sub folders of the ‘bin’ folder to load plugins. 
&lt;ul&gt;
&lt;li&gt;Turns out that ASP.Net doesn’t by default load in DLLs that exist in sub folders of the bin, though from research it looks like standard .Net apps actually do. 
&lt;li&gt;Another interesting point was that if you try to copy a DLL into a sub folder of the bin during application pre-init you get a funky error:&amp;nbsp; “Storage scopes cannot be created when _AppStart is executing”. It seems that ASP.Net is monitoring all changes in the bin folder regardless of whether or not they are in sub folders but still doesn’t load or reference those assemblies. &lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;h2&gt;An easy solution&lt;/h2&gt;
&lt;p&gt;So, the easy solution is to just set a &lt;a href="http://msdn.microsoft.com/en-us/library/823z9h8w%28vs.71%29.aspx" target="_blank"&gt;‘privatePath’ on the ‘probing’ element&lt;/a&gt; in your web.config to tell the AppDomain to also look for Assemblies/Types in the specified folders. I did try this before when trying to load plugins from sub folders in the bin and couldn’t get it to work. I’m not sure if I was ‘doing it wrong’ but it definitely wasn’t working then, either that or attempting to set this in sub folders of the bin just doesn’t work.&lt;/p&gt;
&lt;div id="scid:9D7513F9-C04C-4721-824A-2B34F0212519:f5d93897-6e1d-4814-bf75-c9e4c57ad588" class="wlWriterSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"&gt;&lt;pre style="overflow: auto; height: 68px; width: 680px; background-color: white"&gt;&lt;div&gt;&lt;!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--&gt;&lt;span style="color: #000000"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000"&gt;runtime&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;
  &lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000"&gt;assemblyBinding xmlns&lt;/span&gt;&lt;span style="color: #000000"&gt;=&lt;/span&gt;&lt;span style="color: #800000"&gt;"&lt;/span&gt;&lt;span style="color: #800000"&gt;urn:schemas-microsoft-com:asm.v1&lt;/span&gt;&lt;span style="color: #800000"&gt;"&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;       
    &lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000"&gt;probing privatePath&lt;/span&gt;&lt;span style="color: #000000"&gt;=&lt;/span&gt;&lt;span style="color: #800000"&gt;"&lt;/span&gt;&lt;span style="color: #800000"&gt;Plugins/temp&lt;/span&gt;&lt;span style="color: #800000"&gt;"&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #000000"&gt;/&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&lt;/div&gt;
&lt;h1&gt;DLL file locking&lt;/h1&gt;
&lt;p&gt;Since plugin DLLs get locked by the CLR when they are loaded, we need to work around this. The solution is to shadow copy the DLLs to another folder on application pre-init. As mentioned previously, this is one of the ways to get plugins loaded in Full Trust and in my opinion is the nicest way to do it since it kills 2 birds with one stone. In Medium Trust however, we’ll have to jump through some hoops and shadow copy the DLLs to a temp folder that exists within the web application. IMPORTANT: When you’re copying DLLs you might be tempted to modify the name of the DLL by adding a version number or similar, but this will NOT work and you’ll get a &lt;em&gt;“The located assembly's manifest definition … does not match the assembly reference.” &lt;/em&gt;exception.&lt;/p&gt;
&lt;h1&gt;Solution&lt;/h1&gt;
&lt;p&gt;&lt;em&gt;&lt;font size="2"&gt;UPDATE: The latest version of this code can be found in the Umbraco v5 source code. The following code does work but there’s been a lot of enhancements to it in the Umbraco core. Here’s the latest changeset as of 16/16/2012 &lt;a href="https://bitbucket.org/Shandem/umbracov5/src/bc972b4dd5f8/Source/Libraries/Umbraco.Cms.Web/System/PluginManager.cs" target="_blank"&gt;Umbraco v5 PluginManager.cs&lt;/a&gt;&lt;/font&gt;&lt;/em&gt;&lt;em&gt;&lt;font size="2"&gt;&lt;/font&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Working in Full Trust, the simplest solution is to shadow copy your plugin DLLs into your AppDomain DynamicDirectory. Working in Medium Trust you’ll need to do the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;On application pre-init: 
&lt;ul&gt;
&lt;li&gt;Shadow copy all of your plugin DLLs to a temporary folder in your web application (not in the ‘bin’) 
&lt;li&gt;Add all of the copied DLLs to be referenced by the BuildManager &lt;/li&gt;&lt;/ul&gt;
&lt;li&gt;Add all folder paths to the &lt;em&gt;privatePath&lt;/em&gt; attribute of the &lt;em&gt;probing&lt;/em&gt; element in your web.config to point to where you will be copying your DLLs 
&lt;ul&gt;
&lt;li&gt;If you have more than one, you need to semi-colon separate them &lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;Thanks to &lt;a href="http://twitter.com/gblock" target="_blank"&gt;Glenn Block&lt;/a&gt; @ Microsoft who gave me a few suggestions regarding DLL file locking with MEF, Assembly load contexts and probing paths! You put me back on track after I had pretty much given up.&lt;/p&gt;
&lt;p&gt;Here’s the code to do the shadow copying and providing the Assemblies to the BuildManager on application pre-init (&lt;em&gt;make sure you set the privatePath on the probing element in your web.config first!!&lt;/em&gt;)&lt;/p&gt;
&lt;div id="scid:9D7513F9-C04C-4721-824A-2B34F0212519:6bc6b791-155d-43bb-a79a-06f5660a311f" class="wlWriterSmartContent" style="float: none; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px"&gt;&lt;pre style="overflow: auto; height: 708px; width: 680px; background-color: white"&gt;&lt;div&gt;&lt;!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--&gt;&lt;span style="color: #0000ff"&gt;using&lt;/span&gt;&lt;span style="color: #000000"&gt; System.Linq;
&lt;/span&gt;&lt;span style="color: #0000ff"&gt;using&lt;/span&gt;&lt;span style="color: #000000"&gt; System.Web;
&lt;/span&gt;&lt;span style="color: #0000ff"&gt;using&lt;/span&gt;&lt;span style="color: #000000"&gt; System.IO;
&lt;/span&gt;&lt;span style="color: #0000ff"&gt;using&lt;/span&gt;&lt;span style="color: #000000"&gt; System.Web.Hosting;
&lt;/span&gt;&lt;span style="color: #0000ff"&gt;using&lt;/span&gt;&lt;span style="color: #000000"&gt; System.Web.Compilation;
&lt;/span&gt;&lt;span style="color: #0000ff"&gt;using&lt;/span&gt;&lt;span style="color: #000000"&gt; System.Reflection;

[assembly: PreApplicationStartMethod(&lt;/span&gt;&lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;&lt;span style="color: #000000"&gt;(PluginFramework.Plugins.PreApplicationInit), &lt;/span&gt;&lt;span style="color: #800000"&gt;"&lt;/span&gt;&lt;span style="color: #800000"&gt;Initialize&lt;/span&gt;&lt;span style="color: #800000"&gt;"&lt;/span&gt;&lt;span style="color: #000000"&gt;)]

&lt;/span&gt;&lt;span style="color: #0000ff"&gt;namespace&lt;/span&gt;&lt;span style="color: #000000"&gt; PluginFramework.Plugins
{
    &lt;/span&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #0000ff"&gt;class&lt;/span&gt;&lt;span style="color: #000000"&gt; PreApplicationInit
    {

        &lt;/span&gt;&lt;span style="color: #0000ff"&gt;static&lt;/span&gt;&lt;span style="color: #000000"&gt; PreApplicationInit()
        {
            PluginFolder &lt;/span&gt;&lt;span style="color: #000000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #0000ff"&gt;new&lt;/span&gt;&lt;span style="color: #000000"&gt; DirectoryInfo(HostingEnvironment.MapPath(&lt;/span&gt;&lt;span style="color: #800000"&gt;"&lt;/span&gt;&lt;span style="color: #800000"&gt;~/plugins&lt;/span&gt;&lt;span style="color: #800000"&gt;"&lt;/span&gt;&lt;span style="color: #000000"&gt;));
            ShadowCopyFolder &lt;/span&gt;&lt;span style="color: #000000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #0000ff"&gt;new&lt;/span&gt;&lt;span style="color: #000000"&gt; DirectoryInfo(HostingEnvironment.MapPath(&lt;/span&gt;&lt;span style="color: #800000"&gt;"&lt;/span&gt;&lt;span style="color: #800000"&gt;~/plugins/temp&lt;/span&gt;&lt;span style="color: #800000"&gt;"&lt;/span&gt;&lt;span style="color: #000000"&gt;));
        }

        &lt;/span&gt;&lt;span style="color: #808080"&gt;///&lt;/span&gt;&lt;span style="color: #008000"&gt; &lt;/span&gt;&lt;span style="color: #808080"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000"&gt;
        &lt;/span&gt;&lt;span style="color: #808080"&gt;///&lt;/span&gt;&lt;span style="color: #008000"&gt; The source plugin folder from which to shadow copy from
        &lt;/span&gt;&lt;span style="color: #808080"&gt;///&lt;/span&gt;&lt;span style="color: #008000"&gt; &lt;/span&gt;&lt;span style="color: #808080"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000"&gt;
        &lt;/span&gt;&lt;span style="color: #808080"&gt;///&lt;/span&gt;&lt;span style="color: #008000"&gt; &lt;/span&gt;&lt;span style="color: #808080"&gt;&amp;lt;remarks&amp;gt;&lt;/span&gt;&lt;span style="color: #008000"&gt;
        &lt;/span&gt;&lt;span style="color: #808080"&gt;///&lt;/span&gt;&lt;span style="color: #008000"&gt; This folder can contain sub folderst to organize plugin types
        &lt;/span&gt;&lt;span style="color: #808080"&gt;///&lt;/span&gt;&lt;span style="color: #008000"&gt; &lt;/span&gt;&lt;span style="color: #808080"&gt;&amp;lt;/remarks&amp;gt;&lt;/span&gt;&lt;span style="color: #808080"&gt;
&lt;/span&gt;&lt;span style="color: #000000"&gt;        &lt;/span&gt;&lt;span style="color: #0000ff"&gt;private&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #0000ff"&gt;static&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #0000ff"&gt;readonly&lt;/span&gt;&lt;span style="color: #000000"&gt; DirectoryInfo PluginFolder;

        &lt;/span&gt;&lt;span style="color: #808080"&gt;///&lt;/span&gt;&lt;span style="color: #008000"&gt; &lt;/span&gt;&lt;span style="color: #808080"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000"&gt;
        &lt;/span&gt;&lt;span style="color: #808080"&gt;///&lt;/span&gt;&lt;span style="color: #008000"&gt; The folder to shadow copy the plugin DLLs to use for running the app
        &lt;/span&gt;&lt;span style="color: #808080"&gt;///&lt;/span&gt;&lt;span style="color: #008000"&gt; &lt;/span&gt;&lt;span style="color: #808080"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span style="color: #808080"&gt;
&lt;/span&gt;&lt;span style="color: #000000"&gt;        &lt;/span&gt;&lt;span style="color: #0000ff"&gt;private&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #0000ff"&gt;static&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #0000ff"&gt;readonly&lt;/span&gt;&lt;span style="color: #000000"&gt; DirectoryInfo ShadowCopyFolder;

        &lt;/span&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #0000ff"&gt;static&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #0000ff"&gt;void&lt;/span&gt;&lt;span style="color: #000000"&gt; Initialize()
        {            
            Directory.CreateDirectory(ShadowCopyFolder.FullName);

            &lt;/span&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;span style="color: #008000"&gt;clear out plugins)&lt;/span&gt;&lt;span style="color: #008000"&gt;
&lt;/span&gt;&lt;span style="color: #000000"&gt;            &lt;/span&gt;&lt;span style="color: #0000ff"&gt;foreach&lt;/span&gt;&lt;span style="color: #000000"&gt; (var f &lt;/span&gt;&lt;span style="color: #0000ff"&gt;in&lt;/span&gt;&lt;span style="color: #000000"&gt; ShadowCopyFolder.GetFiles(&lt;/span&gt;&lt;span style="color: #800000"&gt;"&lt;/span&gt;&lt;span style="color: #800000"&gt;*.dll&lt;/span&gt;&lt;span style="color: #800000"&gt;"&lt;/span&gt;&lt;span style="color: #000000"&gt;, SearchOption.AllDirectories))
            {
                f.Delete();
            }            

            &lt;/span&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;span style="color: #008000"&gt;shadow copy files&lt;/span&gt;&lt;span style="color: #008000"&gt;
&lt;/span&gt;&lt;span style="color: #000000"&gt;            &lt;/span&gt;&lt;span style="color: #0000ff"&gt;foreach&lt;/span&gt;&lt;span style="color: #000000"&gt; (var plug &lt;/span&gt;&lt;span style="color: #0000ff"&gt;in&lt;/span&gt;&lt;span style="color: #000000"&gt; PluginFolder.GetFiles(&lt;/span&gt;&lt;span style="color: #800000"&gt;"&lt;/span&gt;&lt;span style="color: #800000"&gt;*.dll&lt;/span&gt;&lt;span style="color: #800000"&gt;"&lt;/span&gt;&lt;span style="color: #000000"&gt;, SearchOption.AllDirectories))
            {
                var di &lt;/span&gt;&lt;span style="color: #000000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; Directory.CreateDirectory(Path.Combine(ShadowCopyFolder.FullName, plug.Directory.Name));
                &lt;/span&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;span style="color: #008000"&gt; NOTE: You cannot rename the plugin DLL to a different name, it will fail because the assembly name is part if it's manifest
                &lt;/span&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;span style="color: #008000"&gt; (a reference to how assemblies are loaded: &lt;/span&gt;&lt;span style="color: #008000; text-decoration: underline"&gt;http://msdn.microsoft.com/en-us/library/yx7xezcf&lt;/span&gt;&lt;span style="color: #008000"&gt; )&lt;/span&gt;&lt;span style="color: #008000"&gt;
&lt;/span&gt;&lt;span style="color: #000000"&gt;                File.Copy(plug.FullName, Path.Combine(di.FullName, plug.Name), &lt;/span&gt;&lt;span style="color: #0000ff"&gt;true&lt;/span&gt;&lt;span style="color: #000000"&gt;);
            }
            
            &lt;/span&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;span style="color: #008000"&gt; Now, we need to tell the BuildManager that our plugin DLLs exists and to reference them.
            &lt;/span&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;span style="color: #008000"&gt; There are different Assembly Load Contexts that we need to take into account which 
            &lt;/span&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;span style="color: #008000"&gt; are defined in this article here:
            &lt;/span&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;span style="color: #008000"&gt; &lt;/span&gt;&lt;span style="color: #008000; text-decoration: underline"&gt;http://blogs.msdn.com/b/suzcook/archive/2003/05/29/57143.aspx&lt;/span&gt;&lt;span style="color: #008000"&gt;

            &lt;/span&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;span style="color: #008000"&gt; * This will put the plugin assemblies in the 'Load' context
            &lt;/span&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;span style="color: #008000"&gt; This works but requires a 'probing' folder be defined in the web.config&lt;/span&gt;&lt;span style="color: #008000"&gt;
&lt;/span&gt;&lt;span style="color: #000000"&gt;            &lt;/span&gt;&lt;span style="color: #0000ff"&gt;foreach&lt;/span&gt;&lt;span style="color: #000000"&gt; (var a &lt;/span&gt;&lt;span style="color: #0000ff"&gt;in&lt;/span&gt;&lt;span style="color: #000000"&gt;
                ShadowCopyFolder
                .GetFiles(&lt;/span&gt;&lt;span style="color: #800000"&gt;"&lt;/span&gt;&lt;span style="color: #800000"&gt;*.dll&lt;/span&gt;&lt;span style="color: #800000"&gt;"&lt;/span&gt;&lt;span style="color: #000000"&gt;, SearchOption.AllDirectories)
                .Select(x &lt;/span&gt;&lt;span style="color: #000000"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;  AssemblyName.GetAssemblyName(x.FullName))
                .Select(x &lt;/span&gt;&lt;span style="color: #000000"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color: #000000"&gt; Assembly.Load(x.FullName)))
            {
                BuildManager.AddReferencedAssembly(a);
            }

            &lt;/span&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;span style="color: #008000"&gt; * This will put the plugin assemblies in the 'LoadFrom' context
            &lt;/span&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;span style="color: #008000"&gt; This works but requires a 'probing' folder be defined in the web.config
            &lt;/span&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;span style="color: #008000"&gt; This is the slowest and most error prone version of the Load contexts.            
            &lt;/span&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;span style="color: #008000"&gt;foreach (var a in
            &lt;/span&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;span style="color: #008000"&gt;    ShadowCopyFolder
            &lt;/span&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;span style="color: #008000"&gt;    .GetFiles("*.dll", SearchOption.AllDirectories)
            &lt;/span&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;span style="color: #008000"&gt;    .Select(plug =&amp;gt; Assembly.LoadFrom(plug.FullName)))
            &lt;/span&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;span style="color: #008000"&gt;{
            &lt;/span&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;span style="color: #008000"&gt;    BuildManager.AddReferencedAssembly(a);
            &lt;/span&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;span style="color: #008000"&gt;}

            &lt;/span&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;span style="color: #008000"&gt; * This will put the plugin assemblies in the 'Neither' context ( i think )
            &lt;/span&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;span style="color: #008000"&gt; This nearly works but fails during view compilation.
            &lt;/span&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;span style="color: #008000"&gt; This DOES work for resolving controllers but during view compilation which is done with the RazorViewEngine, 
            &lt;/span&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;span style="color: #008000"&gt; the CodeDom building doesn't reference the plugin assemblies directly.
            &lt;/span&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;span style="color: #008000"&gt;foreach (var a in
            &lt;/span&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;span style="color: #008000"&gt;    ShadowCopyFolder
            &lt;/span&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;span style="color: #008000"&gt;    .GetFiles("*.dll", SearchOption.AllDirectories)
            &lt;/span&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;span style="color: #008000"&gt;    .Select(plug =&amp;gt; Assembly.Load(File.ReadAllBytes(plug.FullName))))
            &lt;/span&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;span style="color: #008000"&gt;{
            &lt;/span&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;span style="color: #008000"&gt;    BuildManager.AddReferencedAssembly(a);
            &lt;/span&gt;&lt;span style="color: #008000"&gt;//&lt;/span&gt;&lt;span style="color: #008000"&gt;}&lt;/span&gt;&lt;span style="color: #008000"&gt;
&lt;/span&gt;&lt;span style="color: #000000"&gt;
        }
    }
}
&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&lt;/div&gt;</description>
      <pubDate>Thu, 23 Mar 2023 15:08:09 Z</pubDate>
      <a10:updated>2023-03-23T15:08:09Z</a10:updated>
    </item>
    <item>
      <guid isPermaLink="false">1270</guid>
      <link>https://shazwazza.com/post/umbraco-jupiter-plugins-part-2-routing/</link>
      <category>ASP.Net</category>
      <category>Umbraco</category>
      <title>Umbraco Jupiter Plugins - Part 2 - Routing</title>
      <description>&lt;p&gt;This is the second blog post in a series of posts relating to building plugins for Umbraco v5 (Jupiter). &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Related Posts:&lt;/strong&gt;&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;&lt;a href="http://shazwazza.com/post/Umbraco-Jupiter-Plugins-Part-1.aspx"&gt;Umbraco Jupiter Plugins – Part 1&lt;/a&gt;&lt;/li&gt; &lt;/ol&gt;  &lt;h2&gt;Disclaimer&lt;/h2&gt;  &lt;p&gt;&lt;em&gt;This post is about developing for Umbraco v5 (Jupiter) which at the time of this post is still under development. The technical details described below may change by the time Umbraco Jupiter is released. If you have feedback on the technical implementation details, please comment below.&lt;/em&gt;&lt;/p&gt;  &lt;h1&gt;Routing &amp;amp; URLs&lt;/h1&gt;  &lt;p&gt;As mentioned in the &lt;a href="http://shazwazza.com/post/Umbraco-Jupiter-Plugins-Part-1.aspx"&gt;previous post&lt;/a&gt; Umbraco Jupiter will consist of many types of plugins, and of those plugins many of them exist as &lt;a href="http://www.asp.net/mvc/tutorials/asp-net-mvc-controller-overview-cs" target="_blank"&gt;MVC Controllers&lt;/a&gt;.&amp;#160; Each controller has an Action which a URL is routed to, this means that each Controller plugin in Jupiter requires it’s own unique URLs. The good news is that you as a package developer need not worry about managing these URLs and routes, Jupiter will conveniently do all of this for you. &lt;/p&gt;  &lt;h1&gt;Packages &amp;amp; Areas&lt;/h1&gt;  &lt;p&gt;My previous post mentioned that a ‘Package’ in Jupiter is a collection of ‘Plugins’ and as it turns out, Plugins can’t really function unless they are part of a Package. In it’s simplest form, a Package in v5 is a folder which contains Plugins that exists in the &lt;strong&gt;~/Plugins/Packages&lt;/strong&gt; sub folder. The folder name of the package becomes very important because it is used in setting up the routes to&amp;#160; create the unique URLs which map to the MVC Controller plugins. Package developers should be aware that they should name their folder to something that is reasonably unique so it doesn’t overlap with other Package folder names. During package installation, Jupiter will check for uniqueness in Package folder names to ensure there is no overlap (&lt;em&gt;there will be an entirely separate post on how to create deployment packages and how to install them&lt;/em&gt;).&lt;/p&gt;  &lt;p&gt;Here’s a quick example: If I have a Package that contains a &lt;em&gt;Tree &lt;/em&gt;plugin called &lt;em&gt;TestTree&lt;/em&gt; (which is in fact an MVC Controller) and I’ve called my Package folder ‘&lt;em&gt;Shazwazza’&lt;/em&gt;, which exists at &lt;strong&gt;~/Plugins/Packages/Shazwazza &lt;/strong&gt;then the URL to return the JSON for the tree is: &lt;a href="http://localhost/Umbraco/Shazwazza/Trees/TestTree/Index"&gt;http://localhost/Umbraco/Shazwazza/Trees/TestTree/Index&lt;/a&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Similarly, if I have a &lt;em&gt;Editor&lt;/em&gt; plugin called &lt;em&gt;TestEditor &lt;/em&gt;with an action called &lt;em&gt;Edit&lt;/em&gt;, then a URL to render the Edit Action is:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://localhost/Umbraco/Shazwazza/Editors/TestEditor/Edit"&gt;http://localhost/Umbraco/Shazwazza/Editors/TestEditor/Edit&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;If you’ve worked with MVC, you’ll probably know what an &lt;a href="http://msdn.microsoft.com/en-us/library/ee671793.aspx" target="_blank"&gt;MVC Area&lt;/a&gt; is. The way that Jupiter creates the routes for Packages/Plugins is by creating an MVC Area for each Package. This is how it deals with the probability that different Package developers may create MVC Controllers with the same name. MVC routes are generally based just on a Controller name and an Action name which wouldn’t really work for us because there’s bound to be overlap amongst Package developers, so by creating an Area for each Package the route becomes unique to a combination of Controller name, Action name and Area name.&amp;#160; MVC also determines where to look for Views based on Area name which solves another issue of multiple Packages installed with the same View names.&lt;/p&gt;  &lt;h1&gt;Whats next?&lt;/h1&gt;  &lt;p&gt;In the coming blog posts I’ll talk about &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;how plugins are installed and loaded &lt;/li&gt;    &lt;li&gt;how and where the Views are stored that the plugins reference &lt;/li&gt;    &lt;li&gt;how to create all of the different types of plugins &lt;/li&gt; &lt;/ul&gt;  &lt;h1&gt;Code Garden 2011&lt;/h1&gt;  &lt;p&gt;I’ll be doing a talk on &lt;a href="http://codegarden11.com/sessions/day-2/slot-one/get-plugged-in-to-umbraco-jupiter.aspx" target="_blank"&gt;Plugins for Umbraco Jupiter&lt;/a&gt; at &lt;a href="http://codegarden11.com/" target="_blank"&gt;Code Garden 2011&lt;/a&gt; this year which will go in to a lot more detail than these blog posts. If you are attending Code Garden already, then hopefully this series will give you a head start on Umbraco v5. If you haven’t got your tickets to Code Garden yet, what are you waiting for?! We have so much information to share with you :)&lt;/p&gt;</description>
      <pubDate>Thu, 23 Mar 2023 15:08:09 Z</pubDate>
      <a10:updated>2023-03-23T15:08:09Z</a10:updated>
    </item>
    <item>
      <guid isPermaLink="false">1283</guid>
      <link>https://shazwazza.com/post/registering-custom-components-in-ioc-for-umbraco-5-plugins/</link>
      <category>Umbraco</category>
      <title>Registering custom components in IoC for Umbraco 5 plugins</title>
      <description>&lt;p&gt;Sometimes you might need to add some of your own components to the IoC container in Umbraco 5 for your plugins to function. We’ve made this extremely easy to do and it only requires 2 steps:&lt;/p&gt; &lt;p&gt;Create a custom class that implements &lt;em&gt;Umbraco.Framework.DependencyManagement.IDependencyDemandBuilder . &lt;/em&gt;&lt;strong&gt;Ensure that this class does not have any constructor parameters otherwise it will not work. &lt;/strong&gt;There’s only one method to implement and you can use the containerBuilder parameter to add stuff to the IoC container:&lt;/p&gt;  &lt;div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;p&gt;&lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Build(IContainerBuilder containerBuilder, IBuilderContext context);&lt;/p&gt;&lt;/pre&gt;&lt;br&gt;&lt;/div&gt;

&lt;p&gt;Next you need to attribute your plugin (i.e. Tree, Editor, Menu Item, Property Editor, Surface Controller, etc….) to tell it which ‘Demand Builder’ to use. Easiest to explain with an example:&lt;/p&gt;
&lt;div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper"&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;[DemandsDependencies(&lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(MyCustomBuilder))]&lt;br&gt;[Tree(&lt;span style="color: #006080"&gt;"4883C970-2499-488E-A963-5204F6C6F840"&lt;/span&gt;, &lt;span style="color: #006080"&gt;"My Tree"&lt;/span&gt;)]&lt;br&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; MyCustomTree : TreeController&lt;/pre&gt;&lt;br&gt;&lt;/div&gt;
&lt;p&gt;The above code will ensure that the ‘Demand Builder’ of type MyCustomBuilder will be executed when this plugin is loaded&lt;/p&gt;
&lt;p&gt;Thats it! Now you can add anything you need to the IoC container if you require this for your plugin.&lt;/p&gt;</description>
      <pubDate>Thu, 23 Mar 2023 15:08:08 Z</pubDate>
      <a10:updated>2023-03-23T15:08:08Z</a10:updated>
    </item>
    <item>
      <guid isPermaLink="false">1254</guid>
      <link>https://shazwazza.com/post/how-to-inspect-assemblies-with-reflection-before-including-them-in-your-application/</link>
      <category>Web Development</category>
      <title>How to inspect assemblies with reflection before including them in your application</title>
      <description>&lt;p&gt;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:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Checking if the package has missing assembly references&lt;/li&gt;
&lt;li&gt;Checking if the assembly references obsolete types that might make the package unstable&lt;/li&gt;
&lt;li&gt;Checking the .Net targeted framework of the assembly&lt;/li&gt;
&lt;li&gt;Any other assembly inspection to determine it is compatible with your app&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To do this you can load assemblies using &lt;em&gt;Assembly.ReflectionOnlyLoadFrom &lt;/em&gt;and &lt;em&gt;Assembly.ReflectionOnlyLoad &lt;/em&gt;methods which load assemblies into a special &lt;a rel="noopener" href="http://msdn.microsoft.com/en-us/library/dd153782.aspx" target="_blank"&gt;assembly load context&lt;/a&gt; called “reflection-only context” which will safely let you inspect these assemblies.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Further reading:&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;A great article on &lt;/em&gt;&lt;a rel="noopener" href="http://blogs.msdn.com/b/junfeng/archive/2004/08/24/219691.aspx" target="_blank"&gt;&lt;em&gt;Reflection Only Assembly Loading&lt;/em&gt;&lt;/a&gt;&lt;em&gt; and if you want to know more about assembly load contexts, here’s an &lt;/em&gt;&lt;a rel="noopener" href="http://blogs.msdn.com/b/suzcook/archive/2003/05/29/57143.aspx" target="_blank"&gt;&lt;em&gt;explanation&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;Loading in assemblies&lt;/h2&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;p&gt;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 &lt;em&gt;AppDomain.ReflectionOnlyAssemblyResolve &lt;/em&gt;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.&lt;/p&gt;
&lt;p&gt;The first thing to do is setup the event handler&lt;/p&gt;
&lt;pre class="csharpcode"&gt;AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += (s, e) =&amp;gt;
{
    var a = Assembly.ReflectionOnlyLoad(e.Name);
    &lt;span class="kwrd"&gt;if&lt;/span&gt; (a == &lt;span class="kwrd"&gt;null&lt;/span&gt;) &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; TypeLoadException(&lt;span class="str"&gt;"Could not load assembly "&lt;/span&gt; + e.Name);
    &lt;span class="kwrd"&gt;return&lt;/span&gt; a;
};&lt;/pre&gt;
&lt;p&gt;Next we need to load all of the assembly files in the folder&lt;/p&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;foreach&lt;/span&gt; (var f &lt;span class="kwrd"&gt;in&lt;/span&gt; files) Assembly.ReflectionOnlyLoadFrom(f);&lt;/pre&gt;
&lt;p&gt;Then load all of their referenced assemblies in to the reflection context&lt;/p&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="rem"&gt;//Then load each referenced assembly into the context&lt;/span&gt;
var assembliesWithErrors = &lt;span class="kwrd"&gt;new&lt;/span&gt; List&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;&amp;gt;();
&lt;span class="kwrd"&gt;foreach&lt;/span&gt; (var f &lt;span class="kwrd"&gt;in&lt;/span&gt; files)
{
    var reflectedAssembly = Assembly.ReflectionOnlyLoadFrom(f);
    &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (var assemblyName &lt;span class="kwrd"&gt;in&lt;/span&gt; reflectedAssembly.GetReferencedAssemblies())
    {
        &lt;span class="kwrd"&gt;try&lt;/span&gt;
        {
            Assembly.ReflectionOnlyLoad(assemblyName.FullName);
        }
        &lt;span class="kwrd"&gt;catch&lt;/span&gt; (FileNotFoundException)
        {
            &lt;span class="rem"&gt;//if an exception occurs it means that a referenced assembly could not be found                        &lt;/span&gt;
            errors.Add(
                &lt;span class="kwrd"&gt;string&lt;/span&gt;.Concat(&lt;span class="str"&gt;"This package references the assembly '"&lt;/span&gt;,
                    assemblyName.Name,
                    &lt;span class="str"&gt;"' which was not found, this package may have problems running"&lt;/span&gt;));
            assembliesWithErrors.Add(f);
        }
    }
}&lt;/pre&gt;
&lt;p&gt;In the &lt;em&gt;catch&lt;/em&gt;, 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.&lt;/p&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="rem"&gt;//now that we have all referenced types into the context we can look up stuff&lt;/span&gt;
&lt;span class="kwrd"&gt;foreach&lt;/span&gt; (var f &lt;span class="kwrd"&gt;in&lt;/span&gt; files.Except(assembliesWithErrors))
{
    &lt;span class="rem"&gt;//now we need to see if they contain any type 'MyType'&lt;/span&gt;
    var reflectedAssembly = Assembly.ReflectionOnlyLoadFrom(f);
    var found = reflectedAssembly.GetExportedTypes()
        .Where(TypeHelper.IsTypeAssignableFrom&amp;lt;MyType&amp;gt;);
    &lt;span class="kwrd"&gt;if&lt;/span&gt; (found.Any())
    {
        dllsWithReference.Add(reflectedAssembly.FullName);
    }
}&lt;/pre&gt;
&lt;h2&gt;Separate AppDomain&lt;/h2&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;h2&gt;Source Code&lt;/h2&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://gist.github.com/Shazwazza/7147978"&gt;https://gist.github.com/Shazwazza/7147978&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Thu, 23 Mar 2023 15:08:08 Z</pubDate>
      <a10:updated>2023-03-23T15:08:08Z</a10:updated>
    </item>
    <item>
      <guid isPermaLink="false">1163</guid>
      <link>https://shazwazza.com/post/umbraco-jupiter-plugins-part-5-surface-controllers/</link>
      <category>Umbraco</category>
      <title>Umbraco Jupiter Plugins - Part 5 - Surface Controllers</title>
      <description>&lt;p&gt;This is the fifth blog post in a series of posts relating to building plugins for Umbraco v5 (Jupiter). This post will explain what a Surface Controller is, what they can be used for and how to create one. &lt;/p&gt; &lt;h2&gt;Disclaimer&lt;/h2&gt; &lt;p&gt;&lt;em&gt;This post is about developing for Umbraco v5 (Jupiter) which at the time of this post is still under development. The technical details described below may change by the time Umbraco Jupiter is released. If you have feedback on the technical implementation details, please comment below.&lt;/em&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Related Posts:&lt;/strong&gt;  &lt;ol&gt; &lt;li&gt;&lt;a href="http://shazwazza.com/post/Umbraco-Jupiter-Plugins-Part-1.aspx"&gt;Umbraco Jupiter Plugins – Part 1&lt;/a&gt;  &lt;li&gt;&lt;a href="http://shazwazza.com/post/Umbraco-Jupiter-Plugins-Part-2-Routing.aspx"&gt;Umbraco Jupiter Plugins – Part 2 – Routing&lt;/a&gt;  &lt;li&gt;&lt;a href="http://shazwazza.com/post/Umbraco-Jupiter-Plugins-Part-3-Trees.aspx"&gt;Umbraco Jupiter Pluings – Part 3 – Trees&lt;/a&gt;  &lt;li&gt;&lt;a href="http://shazwazza.com/post/Umbraco-Jupiter-Plugins-Part-4-Editors.aspx"&gt;Umbraco Jupiter Pluings – Part 4 – Editors&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt; &lt;h1&gt;What is a Surface Controller?&lt;/h1&gt; &lt;p&gt;A Surface Controller is an MVC controller that interacts with the front-end (or render layer) of Umbraco. An example of a Surface Controller could be a controller that has a &lt;a href="http://haacked.com/archive/2009/11/18/aspnetmvc2-render-action.aspx" target="_blank"&gt;Child Action&lt;/a&gt; used to display a Twitter Feed, or a controller that has an Action to accept some posted information from a form. Child Actions on Surface Controller will probably be primarily used for Child Action Macros in Umbraco v5. &lt;/p&gt; &lt;p&gt;Since Surface Controllers are plugins, this means that you can create a package that contains Surface Controllers to distribute whatever front-end functionality you like to Umbraco developers. Surface Controllers, just like Tree Controllers and Editor Controllers get automatically routed for you.&lt;/p&gt; &lt;h1&gt;Creating a Surface Controller&lt;/h1&gt; &lt;p&gt;&lt;em&gt;&lt;strong&gt;Important convention: &lt;/strong&gt;All Surface controller names MUST be suffixed with ‘SurfaceController’. For example, if you are creating a Surface Controller to display system a Twitter feed, you might call your controller: TwitterFeed&lt;strong&gt;SurfaceController&lt;/strong&gt;. If you don’t follow this convention, you’re surface controller wont be routed.&lt;/em&gt;&lt;/p&gt; &lt;p&gt;The first step is to create a class that inherits from the base Surface Controller class:&amp;nbsp; &lt;strong&gt;Umbraco.Cms.Web.Surface.SurfaceController &lt;/strong&gt;&lt;/p&gt; &lt;p&gt;The next step is to define some MVC Action’s to do whatever it is you’d like them to do. Here’s some examples:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Creating an action to partake in a Child Action Macro. To define this is very simple and follows the exact same MVC principles to creating a Child Action… just add a &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.childactiononlyattribute.aspx" target="_blank"&gt;ChildActionOnlyAttribute&lt;/a&gt; to your action method:&lt;/li&gt;&lt;/ul&gt;&lt;pre class="csharpcode"&gt;[ChildActionOnly]
&lt;span class="kwrd"&gt;public&lt;/span&gt; ActionResult DisplayTwitterFeed()&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;ul&gt;
&lt;li&gt;Creating a child action to simply be used as a normal MVC child action which get rendered using @Html.Action or @Html.RenderAction 
&lt;li&gt;Create an action to handle some posted form data:&lt;/li&gt;&lt;/ul&gt;&lt;pre class="csharpcode"&gt;[HttpPost]
&lt;span class="kwrd"&gt;public&lt;/span&gt; ActionResult HandleMyFormSubmission(MyFormModel model) &lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;ul&gt;
&lt;li&gt;Maybe you’d like to track all links clicked on your page. You could use jquery to update all of your links on your page to point to your custom action URL with the real URL as a query string. Then your custom action will log the real link address and redirect the user to where they want to go.&lt;/li&gt;&lt;/ul&gt;
&lt;h2&gt;Plugins vs Non-plugins&lt;/h2&gt;
&lt;p&gt;A Surface Controller ‘can’ be a plugin, meaning that you can create it as a plugin and distribute it as part of a package. However, if you are creating your own Umbraco website and do your development in Visual Studio like most of us, you don’t need to create a Surface Controller with a plugin definition and install it as part of a package, you can just define it locally just like a controller in a normal MVC project. If you do want to ship your Surface Controller as part of a package then you must attribute your Surface Controller with the SurfaceAttribute, and give it an Id. If you don’t do this then Umbraco will detect that its loading a Surface Controller plugin without an Id and throw an exception.&lt;/p&gt;
&lt;h2&gt;As a plugin&lt;/h2&gt;
&lt;p&gt;Standard practice for creating any kind of controller is to put your controllers in the ‘Controllers’ folder (this is not mandatory but a simple convention to follow). So If you’ve created a new project in Visual Studio, you’d create a folder called ‘Controllers’, then create your Surface Controller class with the SurfaceAttribute and an Id:&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Web.Mvc;
&lt;span class="kwrd"&gt;using&lt;/span&gt; Umbraco.Cms.Web.Context;
&lt;span class="kwrd"&gt;using&lt;/span&gt; Umbraco.Cms.Web.Surface;
&lt;span class="kwrd"&gt;using&lt;/span&gt; Umbraco.Framework;

&lt;span class="kwrd"&gt;namespace&lt;/span&gt; MyProject.Controllers
{
    [Surface(&lt;span class="str"&gt;"98625300-6DF0-41AF-A432-83BD0232815A"&lt;/span&gt;)]
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; TwitterFeedSurfaceController : SurfaceController
    {

    }
}&lt;/pre&gt;
&lt;p&gt;Because this Surface Controller is a plugin, you’ll need to attribute your project assembly (just like when creating Trees or Editor plugins). You can declare this in any of your classes or in the AssemblyInfo.cs file.&lt;/p&gt;&lt;pre class="csharpcode"&gt;[assembly: AssemblyContainsPlugins]&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;h2&gt;As a locally declared Surface Controller&lt;/h2&gt;
&lt;p&gt;This is pretty much identical to the above but you don’t have to include the SurfaceAttribute or attribute your assembly. If you’ve got an Umbraco v5 website that you’re working on you should just create a ~/Controllers folder to put your controller in, just as if you were creating a normal MVC project. Then you can create your Surface Controller:&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Web.Mvc;
&lt;span class="kwrd"&gt;using&lt;/span&gt; Umbraco.Cms.Web.Context;
&lt;span class="kwrd"&gt;using&lt;/span&gt; Umbraco.Cms.Web.Surface;
&lt;span class="kwrd"&gt;using&lt;/span&gt; Umbraco.Framework;

&lt;span class="kwrd"&gt;namespace&lt;/span&gt; MyProject.Controllers
{
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; TwitterFeedSurfaceController : SurfaceController
    {

    }
}&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;h1&gt;Using a Surface Controller&lt;/h1&gt;
&lt;p&gt;The usage of a Surface Controller really depends on what you’ve created your surface controller to do. Probably the 3 main ways to use them will be:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create a ChildAction Macro by using the Macro UI in the back office and selecting a child action that you’ve declared on your Surface Controller, then render the macro in your template or inline in the WYSIWYG editor. 
&lt;li&gt;Directly render a child action declared on your Surface Controller by using &lt;em&gt;@Html.Action &lt;/em&gt;or &lt;em&gt;@Html.RenderAction&lt;/em&gt; 
&lt;li&gt;Create an Html form to post data to an action on your Surface Controller using &lt;em&gt;@Html.BeginUmbracoForm &lt;/em&gt;(more on this in the next blog post!)&lt;/li&gt;&lt;/ul&gt;</description>
      <pubDate>Thu, 23 Mar 2023 15:08:08 Z</pubDate>
      <a10:updated>2023-03-23T15:08:08Z</a10:updated>
    </item>
    <item>
      <guid isPermaLink="false">1174</guid>
      <link>https://shazwazza.com/post/umbraco-jupiter-plugins-part-1/</link>
      <category>ASP.Net</category>
      <category>Umbraco</category>
      <title>Umbraco Jupiter Plugins - Part 1</title>
      <description>&lt;p&gt;This is the first blog post in a series of posts relating to building plugins for Umbraco v5 (Jupiter)&lt;/p&gt;  &lt;h2&gt;Disclaimer&lt;/h2&gt;  &lt;p&gt;&lt;em&gt;This post is about developing for Umbraco v5 (Jupiter) which at the time of this post is still under development. The technical details described below may change by the time Umbraco Jupiter is released. If you have feedback on the technical implementation details, please comment below.&lt;/em&gt;&lt;/p&gt;  &lt;h1&gt;What is a plugin&lt;/h1&gt;  &lt;p&gt;Since Umbraco Jupiter has been built from the ground up, we first need to define some v5 terminology:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;Plugin&lt;/strong&gt; = A single functional component that extends Umbraco such as a Tree, an Editor, a Menu Item, etc… &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Package&lt;/strong&gt; = A group of Plugins installed into Umbraco via the ~/Plugins/Packages/&lt;em&gt;[Package Name]&lt;/em&gt; folder &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;The Umbraco v5 back-office has been architected to run entirely on Plugins, in fact the core trees, editors, etc… that are shipped with Umbraco are Plugins in v5.&lt;/p&gt;  &lt;h1&gt;Types of plugins&lt;/h1&gt;  &lt;p&gt;The list of Plugin types will most likely increase from the time of this blog post to when Jupiter is launched but as it stands now here are the types of Plugins supported in v5:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;Property Editors &lt;/strong&gt;      &lt;ul&gt;       &lt;li&gt;This term is new to v5. In v4.x there was no differentiation between a &lt;em&gt;Data Type&lt;/em&gt; and it’s underlying ‘Data Type’ editor. In v5 we’ve made a clear distinction between a ‘Data Type’ (as seen in the &lt;em&gt;Data Type&lt;/em&gt; tree and used as properties for &lt;em&gt;Document Types&lt;/em&gt;) and the underlying editor and pre-value editor that it exposes.&amp;#160; An example of a &lt;em&gt;Property Editor&lt;/em&gt; would be &lt;a href="http://ucomponents.codeplex.com" target="_blank"&gt;uComponents’&lt;/a&gt; Multi-Node Tree Picker. An example of a &lt;em&gt;Data Type&lt;/em&gt; would be when an Umbraco administrator creates a new &lt;em&gt;Data Type &lt;/em&gt;node in the &lt;em&gt;Data Type &lt;/em&gt;tree and assigns the Multi-Node Tree Picker as it’s &lt;em&gt;Property Editor&lt;/em&gt;. &lt;/li&gt;        &lt;li&gt;So uComponents Team, this is where you need to focus your efforts for version 5! &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Menu Items&lt;/strong&gt;       &lt;ul&gt;       &lt;li&gt;Context menu items such as Create, Publish, Audit Trail, etc… are all plugins. &lt;/li&gt;        &lt;li&gt;See &lt;a href="http://shazwazza.com/post/Custom-Actions-in-Umbraco-Jupiter.aspx" target="_blank"&gt;this post&lt;/a&gt; in regards to creating menu items in v5, though there have been some new features added since that article was created which I’ll detail in coming posts in this series. &lt;!--EndFragment--&gt;&lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Editors&lt;/strong&gt;       &lt;ul&gt;       &lt;li&gt;Editor plugins are all of the interactions performed in the right hand editor panel and in modal dialogs in the back-office. &lt;/li&gt;        &lt;li&gt;For example, the Content Editor core plugin in v5 manages the rendering for all views such as editing content, sorting, copying, and moving nodes, and nearly all of the other views that the context menu actions render. &lt;/li&gt;        &lt;li&gt;Editors are comprised mostly of MVC Controllers, Views, JavaScript &amp;amp; CSS. &lt;!--EndFragment--&gt;&lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Trees&lt;/strong&gt;       &lt;ul&gt;       &lt;li&gt;All trees are plugins, for example, the Content tree, Media tree, Document Type tree are all different plugins. &lt;/li&gt;        &lt;li&gt;Trees are actually MVC controllers. &lt;/li&gt;        &lt;li&gt;Tree nodes use &lt;em&gt;Menu Items&lt;/em&gt; to render &lt;em&gt;Editors&lt;/em&gt; &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;&amp;#160;&lt;strong&gt;Presentation Addins (Yet to be officially named)&lt;/strong&gt; &lt;/li&gt;    &lt;ul&gt;     &lt;li&gt;Another type of plugin are Controllers that are installed via packages that interact with the presentation layer, an example of this might be the Controller Action that accepts the post values from a Contour form. &lt;/li&gt;   &lt;/ul&gt; &lt;/ul&gt;  &lt;h1&gt;Whats next?&lt;/h1&gt;  &lt;p&gt;In the coming blog posts I’ll talk about &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;how plugins are installed and loaded &lt;/li&gt;    &lt;li&gt;how the Umbraco routing system works with all of these controllers &lt;/li&gt;    &lt;li&gt;how and where the Views are stored that the plugins reference &lt;/li&gt;    &lt;li&gt;how to create all of the different types of plugins &lt;/li&gt; &lt;/ul&gt;  &lt;h1&gt;Code Garden 2011&lt;/h1&gt;  &lt;p&gt;I’ll be doing a talk on &lt;a href="http://codegarden11.com/sessions/day-2/slot-one/get-plugged-in-to-umbraco-jupiter.aspx" target="_blank"&gt;Plugins for Umbraco Jupiter&lt;/a&gt; at &lt;a href="http://codegarden11.com/" target="_blank"&gt;Code Garden 2011&lt;/a&gt; this year which will go in to a lot more detail than these blog posts. If you are attending Code Garden already, then hopefully this series will give you a head start on Umbraco v5. If you haven’t got your tickets to Code Garden yet, what are you waiting for?! We have so much information to share with you :)&lt;/p&gt;</description>
      <pubDate>Thu, 23 Mar 2023 15:08:08 Z</pubDate>
      <a10:updated>2023-03-23T15:08:08Z</a10:updated>
    </item>
    <item>
      <guid isPermaLink="false">1185</guid>
      <link>https://shazwazza.com/post/umbraco-jupiter-plugins-part-4-editors/</link>
      <category>Umbraco</category>
      <title>Umbraco Jupiter Plugins - Part 4 - Editors</title>
      <description>&lt;p&gt;This is the fourth blog post in a series of posts relating to building plugins for Umbraco v5 (Jupiter). This post will show you how to &lt;strong&gt;get started &lt;/strong&gt;with building an editor. An Editor is the term used to express the editing pane on the right hand side of the back-office. Examples include: the content editor, media editor, document type editor, script editor, etc..&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Related Posts:&lt;/strong&gt;  &lt;ol&gt; &lt;li&gt;&lt;a href="http://shazwazza.com/post/Umbraco-Jupiter-Plugins-Part-1.aspx"&gt;Umbraco Jupiter Plugins – Part 1&lt;/a&gt;  &lt;li&gt;&lt;a href="http://shazwazza.com/post/Umbraco-Jupiter-Plugins-Part-2-Routing.aspx"&gt;Umbraco Jupiter Plugins – Part 2 – Routing&lt;/a&gt;  &lt;li&gt;&lt;a href="http://shazwazza.com/post/Umbraco-Jupiter-Plugins-Part-3-Trees.aspx" target="_blank"&gt;Umbraco Jupiter Pluings – Part 3 – Trees&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt; &lt;h2&gt;Disclaimer&lt;/h2&gt; &lt;p&gt;&lt;em&gt;This post is about developing for Umbraco v5 (Jupiter) which at the time of this post is still under development. The technical details described below may change by the time Umbraco Jupiter is released. If you have feedback on the technical implementation details, please comment below.&lt;/em&gt;  &lt;h1&gt;Defining an Editor&lt;/h1&gt; &lt;p&gt;An Editor in Umbraco v5 is the combination of: An MVC Controller, View(s), JavaScript and CSS. The first step to creating an Editor is to create a class that inherits from the Umbraco base editor class: &lt;strong&gt;Umbraco.Cms.Web.Editors.StandardEditorController.&lt;/strong&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;The next step is to register this editor as an editor plugin. To do this you just need to add an attribute to your class such as:&lt;/p&gt;&lt;pre class="csharpcode"&gt;[Editor(&lt;span class="str"&gt;"ADD307B3-A5F9-4A89-ADAC-72289A5943FF"&lt;/span&gt;)]&lt;/pre&gt;
&lt;p&gt;The mandatory parameter passed to this attribute is the editor plugin ID (this MUST be unique so ensure you generated a new GUID for every single one of your plugins). 
&lt;p&gt;The next thing you’ll need to do to ensure your editor plugin is found and loaded is to ‘advertise’ that your assembly contains a plugin. To do this, just edit your assembly’s AssemblyInfo.cs file and add the following attribute:&lt;pre class="csharpcode"&gt;[assembly: AssemblyContainsPlugins]&lt;/pre&gt;
&lt;h1&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
Creating an Editor&lt;/h1&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Important convention: &lt;/strong&gt;All Editor controller names MUST be suffixed with ‘EditorController’. For example, if you are creating an editor to display system information, you might call your Editor: SystemInfo&lt;strong&gt;EditorController&lt;/strong&gt;. If you don’t follow this convention, you’re editor controller wont be routed.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;When creating an Editor there are a few base classes to choose from. Generally however, you should inherit from: &lt;strong&gt;Umbraco.Cms.Web.Editors.StandardEditorController&lt;/strong&gt;. The other base classes and their hierarchy are as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Umbraco.Cms.Web.Mvc.Controllers.BackOffice.SecuredBackOfficeController 
&lt;ul&gt;
&lt;li&gt;Umbraco.Cms.Web.Editors.BaseEditorController 
&lt;ul&gt;
&lt;li&gt;Umbraco.Cms.Web.Editors.DashboardEditorController 
&lt;ul&gt;
&lt;li&gt;Umbraco.Cms.Web.Editors.StandardEditorController&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;When inheriting from any of the base classes above, you will be required to create a constructor accepting an parameter of type: &lt;strong&gt;IBackOfficeRequestContext &lt;/strong&gt;:&lt;/p&gt;&lt;pre class="csharpcode"&gt;[Editor(&lt;span class="str"&gt;"ADD307B3-A5F9-4A89-ADAC-72289A5943FF"&lt;/span&gt;)]
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; MyEditorController : StandardEditorController
{
    &lt;span class="kwrd"&gt;public&lt;/span&gt; MyEditorController(IBackOfficeRequestContext requestContext)
        : &lt;span class="kwrd"&gt;base&lt;/span&gt;(requestContext)
    {
    }        
}&lt;/pre&gt;
&lt;p&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
The &lt;em&gt;StandardEditorController&lt;/em&gt; has an abstract method: &lt;em&gt;Edit(HiveId id)&lt;/em&gt; that needs to be implemented &lt;em&gt;(the abstract Edit Action is marked as [HttpGet])&lt;/em&gt;&lt;/p&gt;&lt;pre class="csharpcode"&gt;[Editor(&lt;span class="str"&gt;"ADD307B3-A5F9-4A89-ADAC-72289A5943FF"&lt;/span&gt;)]
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; MyEditorController : StandardEditorController
{
    &lt;span class="kwrd"&gt;public&lt;/span&gt; MyEditorController(IBackOfficeRequestContext requestContext)
        : &lt;span class="kwrd"&gt;base&lt;/span&gt;(requestContext)
    {
    }
        
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; ActionResult Edit(HiveId id)
    {
        &lt;span class="kwrd"&gt;return&lt;/span&gt; View();
    }
}&lt;/pre&gt;
&lt;p&gt;Most Editors will be displaying a view to edit data based on a &lt;em&gt;HiveId &lt;/em&gt;which is the unique identifier type for pretty much all data in Umbraco 5. If you are writing an editor to edit data in a custom Hive provider, then this will work seamlessly for you. Even if you are creating an editor for data that you aren’t writing a custom Hive provider for, you can still use HiveId as a unique identifier since it has support for wrapping Guid, Int and String Id types. If however you decide that HiveId isn’t for you, then you can inherit from one of the other editor base classes that doesn’t have the abstract Edit method attached to it and create your own Actions with your own parameters.&lt;/p&gt;
&lt;p&gt;The above Edit Action simply returns a view without a model to be rendered. At this point, you’ll need to know where your view should be stored which has everything to do with MVC Areas or embedding views.&lt;/p&gt;
&lt;h1&gt;MVC Areas &amp;amp; Jupiter Packages&lt;/h1&gt;
&lt;p&gt;In a &lt;a href="http://shazwazza.com/post/Umbraco-Jupiter-Plugins-Part-2-Routing.aspx" target="_blank"&gt;previous post&lt;/a&gt; we talk about how packages in v5 are actually registered as their own &lt;a href="http://msdn.microsoft.com/en-us/library/ee671793.aspx" target="_blank"&gt;MVC Area&lt;/a&gt;. All packages get installed to the following location: ~/App_Plugins/Packages/{YourPackageName} . If you aren’t embedding your views, then they should be stored inside of your package folder. Each plugin type has a specific view folder name that your views should be stored in:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Editor views &amp;amp; partial views: 
&lt;ul&gt;
&lt;li&gt;~/App_Plugins/Packages/{&lt;em&gt;YourPackageName&lt;/em&gt;}/&lt;strong&gt;Editors&lt;/strong&gt;/Views/ {&lt;em&gt;EditorControllerName&lt;/em&gt;}/{ViewName}.cshtml 
&lt;li&gt;~/App_Plugins/Packages/{&lt;em&gt;YourPackageName&lt;/em&gt;}/&lt;strong&gt;Editors&lt;/strong&gt;/Views/Shared/ {&lt;em&gt;ViewName&lt;/em&gt;}.cshtml&lt;/li&gt;&lt;/ul&gt;
&lt;li&gt;Property Editor partial views: 
&lt;ul&gt;
&lt;li&gt;~/App_Plugins/Packages/{&lt;em&gt;YourPackageName&lt;/em&gt;}/&lt;strong&gt;PropertyEditors&lt;/strong&gt;/Views/Shared/ {&lt;em&gt;ViewName&lt;/em&gt;}.cshtml&lt;/li&gt;&lt;/ul&gt;
&lt;li&gt;Dashboard partial views: 
&lt;ul&gt;
&lt;li&gt;~/App_Plugins/Packages/{&lt;em&gt;YourPackageName&lt;/em&gt;}/&lt;strong&gt;Dashboards&lt;/strong&gt;/Views/ {&lt;em&gt;ViewName&lt;/em&gt;}.cshtml&lt;/li&gt;&lt;/ul&gt;
&lt;li&gt;Rendering (front-end) partial views: 
&lt;ul&gt;
&lt;li&gt;~/App_Plugins/Packages/{&lt;em&gt;YourPackageName&lt;/em&gt;}/&lt;strong&gt;Views&lt;/strong&gt;/Partial/ {&lt;em&gt;ViewName&lt;/em&gt;}.cshtml&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;So with the controller created above, I would have a view in the following location:&lt;/p&gt;
&lt;p&gt;~/App_Plugins/{MyPackageName}/Editors/Views/MyEditor/Edit.cshtml&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;NOTE&lt;/strong&gt;: The package name folder will be created when installing your NuGet package and will be based on your NuGet package name and version assigned.&lt;/em&gt;&lt;/p&gt;
&lt;h1&gt;Embedding views&lt;/h1&gt;
&lt;p&gt;Many of the views shipped with v5 are embedded which helps to reduce the number of actual files that are shipped. This is also handy if you don’t want to give the ability for people to change what’s in your markup.&lt;/p&gt;
&lt;p&gt;Embedding a view is really easy:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create a Razor (.cshtml) view in your Package’s project 
&lt;li&gt;View the Properties for this file and choose &lt;em&gt;‘Embedded Resource’&lt;/em&gt; as the ‘Build Action’&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;Now to use the embedded view we use the following syntax:&lt;/p&gt;&lt;pre class="csharpcode"&gt;[Editor(&lt;span class="str"&gt;"ADD307B3-A5F9-4A89-ADAC-72289A5943FF"&lt;/span&gt;)]
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; MyEditorController : StandardEditorController
{
    &lt;span class="kwrd"&gt;public&lt;/span&gt; MyEditorController(IBackOfficeRequestContext requestContext)
        : &lt;span class="kwrd"&gt;base&lt;/span&gt;(requestContext)
    {
    }
        
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; ActionResult Edit(HiveId id)
    {
        &lt;span class="kwrd"&gt;return&lt;/span&gt; View(EmbeddedViewPath.Create(&lt;span class="str"&gt;"MyProject.Editors.Views.Edit.cshtml"&lt;/span&gt;));
    }
}&lt;/pre&gt;
&lt;p&gt;Its important to get the correct path to your view file. In this instance, my view’s path in my project is: &lt;em&gt;MyProject.Editors.Views.Edit.cshtml&lt;/em&gt;&lt;/p&gt;
&lt;h1&gt;Displaying your Editor&lt;/h1&gt;
&lt;p&gt;Most of the time an editor is displayed by clicking on a node in the tree or by accessing a context menu item. In a &lt;a href="http://shazwazza.com/post/Umbraco-Jupiter-Plugins-Part-3-Trees.aspx" target="_blank"&gt;previous post&lt;/a&gt; about creating trees there was a method to create a tree node:&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; UmbracoTreeResult GetTreeData(HiveEntityUri id, FormCollection queryStrings)
{
    NodeCollection.Add(
        CreateTreeNode(id, &lt;span class="kwrd"&gt;null&lt;/span&gt;, &lt;span class="str"&gt;"My only node"&lt;/span&gt;, &lt;span class="kwrd"&gt;string&lt;/span&gt;.Empty, &lt;span class="kwrd"&gt;false&lt;/span&gt;));
    &lt;span class="kwrd"&gt;return&lt;/span&gt; UmbracoTree();
}&lt;/pre&gt;
&lt;p&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
This simply created a tree node that had no editor URL but now that we have an editor, I’ll update the code to click through to my Edit Action:&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; UmbracoTreeResult GetTreeData(HiveId id, FormCollection queryStrings)
{
    NodeCollection.Add(
        CreateTreeNode(id, &lt;span class="kwrd"&gt;null&lt;/span&gt;, &lt;span class="str"&gt;"My only node"&lt;/span&gt;,
        Url.GetEditorUrl(&lt;span class="str"&gt;"MyEditor"&lt;/span&gt;, id, &lt;span class="kwrd"&gt;new&lt;/span&gt; Guid(&lt;span class="str"&gt;"ADD307B3-A5F9-4A89-ADAC-72289A5943FF"&lt;/span&gt;)),
        &lt;span class="kwrd"&gt;false&lt;/span&gt;));
    &lt;span class="kwrd"&gt;return&lt;/span&gt; UmbracoTree();
}&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
GetEditorUrl is an extension method of UrlHelper which has a few overloads for generating an Editor’s Url. In this case we are passing in the Editor’s name and Id with the Id of the current node being rendered in the tree. 
&lt;p&gt;When the node is clicked it will now link to the Edit Action of the MyEditor Controller.&lt;/p&gt;</description>
      <pubDate>Thu, 23 Mar 2023 15:08:08 Z</pubDate>
      <a10:updated>2023-03-23T15:08:08Z</a10:updated>
    </item>
    <item>
      <guid isPermaLink="false">1201</guid>
      <link>https://shazwazza.com/post/umbraco-jupiter-plugins-part-3-trees/</link>
      <category>Umbraco</category>
      <title>Umbraco Jupiter Plugins - Part 3 - Trees</title>
      <description>&lt;p&gt;This is the third blog post in a series of posts relating to building plugins for Umbraco v5 (Jupiter).&amp;nbsp; This post will show you how to &lt;em&gt;get started &lt;/em&gt;with building a tree. A more in-depth example including rendering out child nodes, using many of the inbuilt helper/extension methods will come in a future blog, though in the meantime once you’ve read this post if you want to see more in-depth examples you can easily find them in our v5 source code.  &lt;p&gt;&lt;strong&gt;Related Posts:&lt;/strong&gt;  &lt;ol&gt; &lt;li&gt;&lt;a href="http://shazwazza.com/post/Umbraco-Jupiter-Plugins-Part-1.aspx"&gt;Umbraco Jupiter Plugins – Part 1&lt;/a&gt;  &lt;li&gt;&lt;a href="http://shazwazza.com/post/Umbraco-Jupiter-Plugins-Part-2-Routing.aspx" target="_blank"&gt;Umbraco Jupiter Plugins – Part 2 - Routing&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt; &lt;h2&gt;Disclaimer&lt;/h2&gt; &lt;p&gt;&lt;em&gt;This post is about developing for Umbraco v5 (Jupiter) which at the time of this post is still under development. The technical details described below may change by the time Umbraco Jupiter is released. If you have feedback on the technical implementation details, please comment below.&lt;/em&gt;&lt;/p&gt; &lt;h1&gt;Defining a tree&lt;/h1&gt; &lt;p&gt;A tree in &lt;a href="http://umbraco.com" target="_blank"&gt;Umbraco&lt;/a&gt; v5 is actually an &lt;a href="http://www.asp.net/mvc/tutorials/asp-net-mvc-controller-overview-cs" target="_blank"&gt;MVC Controller&lt;/a&gt; that returns JSON data. The first step to creating a tree is to create a class for your tree that inherits from the Umbraco base tree controller class: &lt;strong&gt;Umbraco.Cms.Web.Trees.TreeController&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;em&gt;&lt;strong&gt;Important convention: &lt;/strong&gt;All Tree controller names MUST be suffixed with ‘TreeController’. For example, if you are creating a tree to display system information, you might call your Tree: SystemInfo&lt;strong&gt;TreeController&lt;/strong&gt;. If you don’t follow this convention, your tree controller won’t be routed.&lt;/em&gt;&lt;/p&gt; &lt;p&gt;The next step is to register this tree as a tree plugin. To do this you just need to add an attribute to your class such as:&lt;/p&gt;&lt;pre class="csharpcode"&gt;[Tree(&lt;span class="str"&gt;"A18108B1-9C86-4B47-AC04-A3089FE8D3EA"&lt;/span&gt;, &lt;span class="str"&gt;"My Custom Tree"&lt;/span&gt;)]&lt;/pre&gt;
&lt;p&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
The two parameters passed to this attribute are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The tree plugin ID (this MUST be unique so ensure you generated a new GUID for every single one of your plugins) 
&lt;li&gt;The tree title. This will be the text rendered for the root node of your tree, however, this can be overridden and you could render out any title that you wish for your root node and it could even be dynamic. Also note that we will be supporting localization for the tree title.&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;The next thing you’ll need to do to ensure your tree plugin is found and loaded is to ‘advertise’ that your assembly contains a tree plugin. To do this, just edit your assembly’s AssemblyInfo.cs file and add the following attribute:&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;strike&gt;&lt;span class="rem"&gt;//mark assembly for export as a tree plugin&lt;/span&gt;
[assembly: TreePluginAssembly]&lt;/strike&gt;&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;pre class="csharpcode"&gt;[assembly: AssemblyContainsPlugins]&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;h1&gt;Creating a tree&lt;/h1&gt;
&lt;h2&gt;Constructor&lt;/h2&gt;
&lt;p&gt;When inheriting from the base Umbraco.Cms.Web.Trees.TreeController, you will be required to create a constructor accepting an parameter of type: &lt;strong&gt;IBackOfficeRequestContext &lt;/strong&gt;:&lt;/p&gt;&lt;pre class="csharpcode"&gt;[Tree(&lt;span class="str"&gt;"A18108B1-9C86-4B47-AC04-A3089FE8D3EA"&lt;/span&gt;, &lt;span class="str"&gt;"My Custom Tree"&lt;/span&gt;)]
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; MyTreeController : TreeController
{
    &lt;span class="kwrd"&gt;public&lt;/span&gt; MyTreeController(IBackOfficeRequestContext requestContext)
        : &lt;span class="kwrd"&gt;base&lt;/span&gt;(requestContext)
    {
    }

    &lt;span class="rem"&gt;//more code will go here....&lt;/span&gt;
    
}&lt;/pre&gt;
&lt;p&gt;The IBackOfficeRequestContext will most likely contain references to everything you’ll need to get the data for your tree. It includes references to: &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Hive 
&lt;li&gt;Umbraco settings 
&lt;li&gt;The TextManager (localization framework) 
&lt;li&gt;All of the registered plugins in the system 
&lt;li&gt;… and a whole lot more&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;However, you’ll be please to know that all plugins including Trees can take part in IoC contructor injection. So, if you want more objects injected into your tree controller you can just add the parameters to your constructor and they’ll be injected so long as they exist in the IoC container.&lt;/p&gt;
&lt;h2&gt;Overriding methods/properties&lt;/h2&gt;
&lt;p&gt;There is one property and one method you need to override:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;RootNodeId&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This property is just a getter and returns the root node id for your tree. Many trees exist at the absolute root of the data which is called the &lt;strong&gt;SystemRoot&lt;/strong&gt;. An example of a tree that exists at the system root would be trees like the: Data Type tree, Macro tree, Packages tree, tc… since they don’t have a heirarchy. Tree’s that have different start node Ids are trees like: Content, Media and Users.&amp;nbsp; Since each one of those entities share the same data structure, we separate these data structures under different start nodes from the SystemRoot.&lt;/p&gt;
&lt;p&gt;For the most part, if you are creating a utility type tree or a custom tree that doesn’t exist under a special hierarchy, the SystemRoot is what you’ll want:&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; HiveEntityUri RootNodeId
{
    get { &lt;span class="kwrd"&gt;return&lt;/span&gt; FixedHiveIds.SystemRoot; }
}&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;GetTreeData&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This method is the method that returns the JSON tree data though to make it easy you don’t have to worry about JSON whatsoever. All you need to do is add &lt;strong&gt;TreeNode&lt;/strong&gt; objects to the existing &lt;strong&gt;NodeCollection&lt;/strong&gt; of the tree controller.&lt;/p&gt;
&lt;p&gt;As a very simple example, if you wanted to render out one node in your tree you could do this:&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; UmbracoTreeResult GetTreeData(HiveEntityUri id, FormCollection queryStrings)
{
    NodeCollection.Add(
        CreateTreeNode(id, &lt;span class="kwrd"&gt;null&lt;/span&gt;, &lt;span class="str"&gt;"My only node"&lt;/span&gt;, &lt;span class="kwrd"&gt;string&lt;/span&gt;.Empty, &lt;span class="kwrd"&gt;false&lt;/span&gt;));
    &lt;span class="kwrd"&gt;return&lt;/span&gt; UmbracoTree();
}&lt;/pre&gt;
&lt;p&gt;The &lt;strong&gt;CreateTreeNode&lt;/strong&gt; is a helper method which is part of the base &lt;strong&gt;TreeController &lt;/strong&gt;class that has many useful overloads. In this example, we’re giving it an id, not passing in any custom query string parameters, a title, not giving it an editor url and tagging the node as not having any children.&lt;/p&gt;
&lt;h1&gt;Registering a tree&lt;/h1&gt;
&lt;p&gt;In order to get your tree to show up in the back office, you need to register the tree in the config file: ~/App_Data/Umbraco/Config/umbraco.cms.trees.config , and here’s all you need to do to put it in the ‘settings’ app (as an example):&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;add&lt;/span&gt; &lt;span class="attr"&gt;application&lt;/span&gt;&lt;span class="kwrd"&gt;="settings"&lt;/span&gt; 
     &lt;span class="attr"&gt;controllerType&lt;/span&gt;&lt;span class="kwrd"&gt;="MyProject.MyTreeController, MyProject"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;

&lt;p&gt;NOTE: At CodeGarden we discussed that you can ship your plugin inside a package and have your own config file deployed which Umbraco will recognize so that you don’t have to edit the already existing file…. This is still true! But we’ll write another blog post about that &lt;img style="border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none" class="wlEmoticon wlEmoticon-smile" alt="Smile" src="https://shazwazza.com/media/articulate-import/wlEmoticon-smile.png"&gt;&lt;/p&gt;
&lt;h1&gt;More in depth example?&lt;/h1&gt;
&lt;p&gt;As I mentioned at the start of this post I’ll write another one detailing our many extension and helper methods when rendering out trees, how to add menu items to your nodes, customize your icons, change the editor for particular nodes, etc… In the meantime though, please have a look at the v5 source code, the trees all exist in the project: &lt;strong&gt;Umbraco.Cms.Web.Trees&lt;/strong&gt;&lt;/p&gt;</description>
      <pubDate>Thu, 23 Mar 2023 15:08:08 Z</pubDate>
      <a10:updated>2023-03-23T15:08:08Z</a10:updated>
    </item>
  </channel>
</rss>