Referenced/External 程序集中的 MapMvcAttributeRoutes

MapMvcAttributeRoutes in Referenced/External Assembly

我正在使用动态加载的程序集作为 MVC 控制器(plugin/add-on 框架)的来源。我找不到在引用的程序集中为控制器映射属性路由的方法。

我尝试从引用的程序集中调用 MapMvcAttributeRoutes(就像文章中建议的那样可以在 Web API 中工作)但是那没有用。

如何在引用的程序集中映射控制器的属性路由?

编辑:

我有一个从文件加载程序集的主 MVC 应用程序。这些程序集的结构如下:

我扩展了用于创建控制器和查找视图的代码,但我找不到关于如何处理外部程序集中指定的(映射)RouteAttribute 的说明,如下所示:

[RoutePrefix("test-addon")]
public class MyTestController : Controller
{
    [Route]
    public ActionResult Page()
    {
        return View(new TestModel { Message = "This is a model test." });
    }
}

我设法找到了解决办法:手动将路由属性解析到路由字典中。可能没有做到 100% 正确,但到目前为止这似乎有效:

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));
            }
        }
    }
}

看似多余的修剪实际上只是为了确保在任何情况下都不会在开头,中间或结尾有任何额外的'/'。