私は、あなたが説明したものと同様のプラグ可能なアーキテクチャを持ち、同じテクノロジASP.NETMVCとMEFを使用するプロジェクトに取り組んできました。認証、承認、およびすべての要求を処理するホストASP.NETMVCアプリケーションがありました。プラグイン(モジュール)はそのサブフォルダーにコピーされました。プラグインは、独自のモデル、コントローラー、ビュー、css、およびjsファイルを持つASP.NETMVCアプリケーションでもありました。これを機能させるために実行した手順は次のとおりです。
MEFの設定
MEFに基づいて、アプリケーションの開始時にすべての構成可能なパーツを検出し、構成可能なパーツのカタログを作成するエンジンを作成しました。これは、アプリケーションの開始時に1回だけ実行されるタスクです。エンジンは、すべてのプラグ可能なパーツを検出する必要があります。この場合bin、ホストアプリケーションのModules(Plugins)フォルダーまたはフォルダーのいずれかにあります。
public class Bootstrapper
{
    private static CompositionContainer CompositionContainer;
    private static bool IsLoaded = false;
    public static void Compose(List<string> pluginFolders)
    {
        if (IsLoaded) return;
        var catalog = new AggregateCatalog();
        catalog.Catalogs.Add(new DirectoryCatalog(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin")));
        foreach (var plugin in pluginFolders)
        {
            var directoryCatalog = new DirectoryCatalog(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Modules", plugin));
            catalog.Catalogs.Add(directoryCatalog);
        }
        CompositionContainer = new CompositionContainer(catalog);
        CompositionContainer.ComposeParts();
        IsLoaded = true;
    }
    public static T GetInstance<T>(string contractName = null)
    {
        var type = default(T);
        if (CompositionContainer == null) return type;
        if (!string.IsNullOrWhiteSpace(contractName))
            type = CompositionContainer.GetExportedValue<T>(contractName);
        else
            type = CompositionContainer.GetExportedValue<T>();
        return type;
    }
}
これは、すべてのMEFパーツの検出を実行するクラスのサンプルコードです。Composeクラスのメソッドが呼び出されたからApplication_StartでメソッドGlobal.asax.csファイル。簡単にするために、コードは縮小されています。
public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        var pluginFolders = new List<string>();
        var plugins = Directory.GetDirectories(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Modules")).ToList();
        plugins.ForEach(s =>
        {
            var di = new DirectoryInfo(s);
            pluginFolders.Add(di.Name);
        });
        AreaRegistration.RegisterAllAreas();
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        Bootstrapper.Compose(pluginFolders);
        ControllerBuilder.Current.SetControllerFactory(new CustomControllerFactory());
        ViewEngines.Engines.Add(new CustomViewEngine(pluginFolders));
    }
}
すべてのプラグインはModules、ホストアプリケーションのルートにあるフォルダーの別のサブフォルダーにコピーされると想定されています。各プラグインサブフォルダーには、Viewsサブフォルダーと各プラグインのDLLが含まれています。Application_Start上記の方法では、カスタムコントローラーファクトリと以下で定義するカスタムビューエンジンも初期化されます。
MEFから読み取るコントローラーファクトリを作成する
リクエストを処理する必要のあるコントローラーを検出するカスタムコントローラーファクトリを定義するためのコードは次のとおりです。
public class CustomControllerFactory : IControllerFactory
{
    private readonly DefaultControllerFactory _defaultControllerFactory;
    public CustomControllerFactory()
    {
        _defaultControllerFactory = new DefaultControllerFactory();
    }
    public IController CreateController(RequestContext requestContext, string controllerName)
    {
        var controller = Bootstrapper.GetInstance<IController>(controllerName);
        if (controller == null)
            throw new Exception("Controller not found!");
        return controller;
    }
    public SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, string controllerName)
    {
        return SessionStateBehavior.Default;
    }
    public void ReleaseController(IController controller)
    {
        var disposableController = controller as IDisposable;
        if (disposableController != null)
        {
            disposableController.Dispose();
        }
    }
}
さらに、各コントローラーには次のExport属性を付ける必要があります。
[Export("Plugin1", typeof(IController))]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class Plugin1Controller : Controller
{
    
    
    public ActionResult Index()
    {
        return View();
    }
}
Export属性コンストラクターの最初のパラメーターは、コントラクト名を指定し、各コントローラーを一意に識別するため、一意である必要があります。PartCreationPolicyコントローラは、複数の要求のために再利用することができないので、非共有に設定する必要があります。
プラグインからビューを見つけることを知っているビューエンジンを作成する
ビューエンジンは慣例によりViewsホストアプリケーションのフォルダー内のビューのみを検索するため、カスタムビューエンジンの作成が必要です。プラグインは別のModulesフォルダーにあるため、ビューエンジンにもそこを探すように指示する必要があります。
public class CustomViewEngine : RazorViewEngine
{
    private List<string> _plugins = new List<string>();
    public CustomViewEngine(List<string> pluginFolders)
    {
        _plugins = pluginFolders;
        ViewLocationFormats = GetViewLocations();
        MasterLocationFormats = GetMasterLocations();
        PartialViewLocationFormats = GetViewLocations();
    }
    public string[] GetViewLocations()
    {
        var views = new List<string>();
        views.Add("~/Views/{1}/{0}.cshtml");
        _plugins.ForEach(plugin =>
            views.Add("~/Modules/" + plugin + "/Views/{1}/{0}.cshtml")
        );
        return views.ToArray();
    }
    public string[] GetMasterLocations()
    {
        var masterPages = new List<string>();
        masterPages.Add("~/Views/Shared/{0}.cshtml");
        _plugins.ForEach(plugin =>
            masterPages.Add("~/Modules/" + plugin + "/Views/Shared/{0}.cshtml")
        );
        return masterPages.ToArray();
    }
}
プラグインで強く型付けされたビューの問題を解決する 
上記のコードのみを使用すると、モデルがbinフォルダーの外部に存在するため、プラグイン(モジュール)で強く型付けされたビューを使用できませんでした。この問題を解決するには、次のリンクをたどってください。