Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save HenrikFrystykNielsen/2907767 to your computer and use it in GitHub Desktop.
Save HenrikFrystykNielsen/2907767 to your computer and use it in GitHub Desktop.
ASP.NET Web API: Controlling assemblies loaded by providing own AssembliesResolver
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.Http.Dispatcher;
using System.Web.Http.SelfHost;
namespace SelfHost
{
class Program
{
static HttpSelfHostServer CreateHost(string address)
{
// Create normal config
HttpSelfHostConfiguration config = new HttpSelfHostConfiguration(address);
// Set our own assembly resolver where we add the assemblies we need
AssembliesResolver assemblyResolver = new AssembliesResolver();
config.Services.Replace(typeof(IAssembliesResolver), assemblyResolver);
// Add a route
config.Routes.MapHttpRoute(
name: "default",
routeTemplate: "api/{controller}/{id}",
defaults: new { controller = "Home", id = RouteParameter.Optional });
HttpSelfHostServer server = new HttpSelfHostServer(config);
server.OpenAsync().Wait();
Console.WriteLine("Listening on " + address);
return server;
}
static void Main(string[] args)
{
// Create and open our host
HttpSelfHostServer server = CreateHost("http://localhost:8080");
Console.WriteLine("Hit ENTER to exit...");
Console.ReadLine();
}
}
class AssembliesResolver : DefaultAssembliesResolver
{
public override ICollection<Assembly> GetAssemblies()
{
ICollection<Assembly> baseAssemblies = base.GetAssemblies();
List<Assembly> assemblies = new List<Assembly>(baseAssemblies);
// Add whatever additional assemblies you wish
return assemblies;
}
}
}
@ikshvakoo
Copy link

ikshvakoo commented Apr 17, 2017

I created a controller assembly containing all my controllers in WebApi 2.0 and created a CustomAssemblyResolver and added code to replace the assembly resolver in Application_Start. Here's what my code looks like:

My CustomAssemblyResolver:

public class CustomAssemblyResolver : DefaultAssembliesResolver
{

public override ICollection<Assembly> GetAssemblies()
{
    ICollection<Assembly> baseAssemblies = base.GetAssemblies();
    List<Assembly> assemblies = new List<Assembly>(baseAssemblies);
    string thirdPartySource = "C:\\Research\\ExCoWebApi\\ExternalControllers";
    if (!string.IsNullOrWhiteSpace(thirdPartySource))
    {
        if (Directory.Exists(thirdPartySource))
        {
            foreach (var file in Directory.GetFiles(thirdPartySource, "*.*", SearchOption.AllDirectories))
            {
                if (Path.GetExtension(file) == ".dll")
                {
                    var externalAssembly = Assembly.LoadFrom(file);

                    baseAssemblies.Add(externalAssembly);
                }
            }
        }
    }
    return baseAssemblies;
}

}

My Application_Start:

protected void Application_Start()
{
    Debugger.Launch();
    AreaRegistration.RegisterAllAreas();
    GlobalConfiguration.Configure(WebApiConfig.Register);
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    BundleConfig.RegisterBundles(BundleTable.Bundles);
    GlobalConfiguration.Configuration.Services.Replace(typeof(IAssembliesResolver), new CustomAssemblyResolver());            
}

As you can see I'm replacing the default assembly resolver with a CustomAssemblyResolver.

Here's how I'm registering route to the third party controller:

public static void RegisterRoutes(RouteCollection routes)
{            
    routes.MapHttpRoute(
        name: "Test",
        routeTemplate: "api/thirdparty/math",
        defaults: new { controller = "Math" }
    );            
}

This is how my MathController looks like that lives in a separate assembly:

public class MathController : ApiController
{
[HttpPost]
public int AddValues(MathRequest request)
{
int response = MathOperations.Add(request.Value1, request.Value2);
return response;
}
}

This is the endpoint I hit via postman: http://localhost/ExCoWebApi/api/thirdparty/math with a POST operation and MathRequest JSON string in the Body and this is what I get as a response:

{ "Message": "No HTTP resource was found that matches the request URI 'http://localhost/ExCoWebApi/api/thirdparty/math'.", "MessageDetail": "No type was found that matches the controller named 'Math'." }

After debugging I found that the AssemblyResolver does get replaced with CustomAssemblyResolver at the Application Start but the problem is the GetAssemblies() method of CustomAssemblyResolver doesn't get called. Hence the assembly containing MathController doesn't get loaded.

What am I missing here??

@vijaykumarkolli
Copy link

How do acheive this in ASP.NET Core 5.0 ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment