Load Razor PreCompiledView class library dll dynamically not working

Sep 7, 2012 at 4:02 AM

It work fine when I add reference of external library which contain PreCompiledView to Main App. When i use plugin framework as specified in http://shazwazza.com/post/Developing-a-plugin-framework-in-ASPNET-with-medium-trust.aspx to dynamically load external library DLL in Main App from private probing folder, the view is not working anymore. It keep displaying YSOD "The view 'Index' or its master was not found or no view engine supports the searched locations". Anyone know how can i remove dependency of adding reference PreCompiled view of external library into Main App?

Coordinator
Sep 7, 2012 at 5:31 AM

I think the problem is that those assemblies normally get activated via WebActivator. But that won't happen if you load them dynamically. You can try doing it manually by calling the RazorGeneratorMvcStart method, which is typically under App_Start in the view library.

Sep 8, 2012 at 4:41 AM

Hi davidebbo, thanks for your reply. However I am using PreApplicationStartMethod on Main App to load the DLL (external library with precompiled view), it work well if the ext lib Controller just return Content("xxxx") instead of View(). Since the dll is loaded even before Application_Start event, i assume everything in DLL should be loaded (controller, ...etc) already including Precompiled View. As for registering view into ViewEngine, i am using Area Registration (triggered in Ext Lib), RegisterAllAreas() scan assembly for AreaRegistration and register routes event.

What puzzle me is since my implementation using PreApplicationStartMethod to load dll can resolve Controller that return Content("xxxx"), why it can't resolve return View().

You suggestion include calling the RazorGeneratorMvcStart method, i can't find it in documentation, can you kindly provide some sample on how to use this method? Appreciate your great help on this. 

Coordinator
Sep 8, 2012 at 7:10 AM

The RazorGeneratorMvcStart class gets added to the project when you use add the RazorGenerator.Mvc nuget package. It has the code that registers the view engine for that assembly. If that's not getting called, views in that assembly won't work.

Dec 21, 2012 at 6:41 PM
Edited Dec 21, 2012 at 6:42 PM

Hello,

anybody found a solution for this?

I am trying to implement a Plugin Infrastructure.

Using PreApplicationStartMethod I am enumerating all Plugin Assemblies, adding them to the referenced assemblies, then registering them to the ViewEngine.

Precompiled Views from the loaded assemblies still won't work. I get the following error "The view '...' or its master was not found or no view engine supports the searched locations"

Any help would be greatly appreciated.

Thank you.

        foreach (var file in fileList)
        {
                var assembly = Assembly.LoadFrom(file.FullName);

                BuildManager.AddReferencedAssembly(assembly);

                var plugins = assembly.GetTypes().Where(type => type.GetInterfaces().Contains(typeof(IPlugin)));
                foreach (var pluginType in plugins)
                {
                    IPlugin plugin = (IPlugin)Activator.CreateInstance(pluginType);
                    plugin.Initialize(dataContext);
                }

                //the view engine will consider all the provided assemblies         
                var engine = new PrecompiledMvcEngine(assembly);

                ViewEngines.Engines.Insert(0, engine);

                // StartPage lookups are done by WebPages.
                VirtualPathFactoryManager.RegisterVirtualPathFactory(engine); 
         }

Coordinator
Dec 21, 2012 at 6:50 PM

Not sure, but you should try to isolate by just trying to enable it for a single assembly to see if that works before doing them all. In the standard scenario, it ends up just being called on one assembly and we know that works, so there must be a difference at some level.

Dec 21, 2012 at 7:59 PM

Thank your for replying.

Well... you se a foreach loop, but there is actually only one Plugin in my test environment.

Coordinator
Dec 21, 2012 at 8:30 PM

Can you verify the engine object discovered views from your plugin? It's in a private variable, but you should be able to inspect that with a debugger.

Dec 21, 2012 at 9:08 PM

Hm... I don't know exactly where to look for this...

I tried to explore private members of the engine object after it has been instanciated.

There is a "_mappings" field that seems close to what you are saying. It's an empty collection.

Is this the right field? What's going wrong?

Dec 21, 2012 at 9:19 PM

Got it! I found this old post:

http://razorgenerator.codeplex.com/workitem/71

About different versions of System.Web.WebPages assembly. My Plugin assembly referenced v 2.0, while the main application was referencing v1.0.

Changed the reference to System.Web.WebPages v1.0 solved this issue: views are working fine from dynamically loaded assemblies!

Coordinator
Dec 24, 2012 at 12:25 AM

Hmmm, I would think that with proper binding redirects (which NuGet adds), it should all have worked out.