I am using dynamically loaded assemblies as a source for MVC Controllers (plugin/add-on framework). I can find no way to map the attribute routes for the Controllers in the referenced assembly.
I tried calling MapMvcAttributeRoutes from within the referenced assembly (like on article suggested would work in Web API) but that did not work.
How do I map attribute routes for Controllers in an referenced assembly?
EDIT:
I have a main MVC application which loads assemblies from a file. These assemblies are structured like so:
I extended the code for creating a controller and finding a View but I can find no instructions on how to handle (map) RouteAttribute
s specified in the external assembly like this:
[RoutePrefix("test-addon")]
public class MyTestController : Controller
{
[Route]
public ActionResult Page()
{
return View(new TestModel { Message = "This is a model test." });
}
}
I managed to find a solution: manually parse Route Attributes into the Route Dictionary. Probably not doing it 100% right but this seems to work so far:
public static void MapMvcRouteAttributes(RouteCollection routes)
{
IRouteHandler routeHandler = new System.Web.Mvc.MvcRouteHandler();
Type[] addOnMvcControllers =
AddOnManager.Default.AddOnAssemblies
.SelectMany(x => x.GetTypes())
.Where(x => typeof(AddOnWebController).IsAssignableFrom(x) && x.Name.EndsWith("Controller"))
.ToArray();
foreach (Type controller in addOnMvcControllers)
{
string controllerName = controller.Name.Substring(0, controller.Name.Length - 10);
System.Web.Mvc.RoutePrefixAttribute routePrefix = controller.GetCustomAttribute<System.Web.Mvc.RoutePrefixAttribute>();
MethodInfo[] actionMethods = controller.GetMethods();
string prefixUrl = routePrefix != null ? routePrefix.Prefix.TrimEnd('/') + "/" : string.Empty;
foreach (MethodInfo method in actionMethods)
{
System.Web.Mvc.RouteAttribute route = method.GetCustomAttribute<System.Web.Mvc.RouteAttribute>();
if (route != null)
{
routes.Add(
new Route(
(prefixUrl + route.Template.TrimStart('/')).TrimEnd('/'),
new RouteValueDictionary { { "controller", controllerName }, { "action", method.Name } },
routeHandler));
}
}
}
}
The seemingly excessive trims are actually just to make sure that under no conditions are there any extra '/' at the start, middle or end.