I am trying to design a modular Web API application (It is not an MVC app!) in which a user in admin role can add or remove modules without restarting the ASP.NET application.
- Module: each module is an assembly (.dll file) that contains at least one class which is derived from
ApiController
. - Routing is based on Attribute Routing in ASP.NET Web API 2
- Production of modules (assemblies) is not in the scope of this question.
- Modules (assembly files) are copied to / deleted from `~/plugins/ folder in the root of the project. This process is not in the scope of this question either.
- The main ASP.NET Web API project has basically only one controller to manage (add/remove) modules. The other controllers will be added as modules.
So the only controller in the main Web API project is:
[RoutePrefix("api/modules")]
public class ModulesController : ApiController
{
private ModuleService _moduleService = new ModuleService();
// GET: api/Modules
[Route]
public IEnumerable<string> Get()
{
return _moduleService.Get().Select(a => a.FullName);
}
// POST: api/Modules/{moduleName}
[Route("{id}")]
public void Post(string id)
{
Assembly _assembly;
var result = _moduleService.TryLoad(id, out _assembly);
if(!result) throw new Exception("problem loading " + id);
// Refresh routs or add the new rout
Configuration.Routes.Clear();
Configuration.MapHttpAttributeRoutes();
// ^ it does not work :(
}
// DELETE: api/Modules/{moduleName}
[Route("{id}")]
public void Delete(string id)
{
_moduleService.Remove(id);
}
}
ModuleService.TryLoad()
simply finds and loads the assembly to the application domain by using AppDomain.CurrentDomain.Load()
. This part is working well.
Configuration.MapHttpAttributeRoutes()
doesn't raise any error, but it breaks the whole routing system. After that line, any routing attempt causes this error:
The object has not yet been initialized. Ensure that HttpConfiguration.EnsureInitialized() is called in the application's startup code after all other initialization code.
I added HttpConfiguration.EnsureInitialized()
to the code, but it didn't resolve the problem (same error).
Questions
- Does this design make any sense? Will it work?
- How can I add a new route to the route collection or refresh the route collection completely?
I solved it.
Firstly, and thanks to @Aleksey L., a little change to the
ModuleController
(addingConfiguration.Initializer(Configuration)
):Then we should extend
DefaultHttpControllerSelector
:And of course we have to replace the default HttpControllerSelector with our HttpControllerSelector, in the
App_start\WebApiConfig.cs
:If anybody is interested in how I implemented theModuleService
, I can upload the code to GitHub.Here is the whole source code in the GitHub: https://github.com/tohidazizi/modular-web-api-poc