Razor strongly typed views in a dynamically loaded assembly do not compile at run time

I have an MVC3 scope in an assembly that is dynamically loaded using MEF.
If I use Webforms view engine with strongly typed views, everything works fine.
If I use the Razor viewer with a dynamic model, it works fine too.

But if I use a strongly typed Razor view , compilation of the view is not performed at run time.

The problem is that the dynamically loaded assembly is not on the list of reference assemblies passed to the C # compiler.

The generated C # code is as follows:

 namespace ASP { using System; /* Other namespaces */ public class _Page_MyApp_Views_Home_Index_cshtml : System.Web.Mvc.WebViewPage<MyApp.ViewModels.Search.IndexViewModel> { /* Generated code */ } } 

And here is the error message:

 Compiler Error Message: CS0246: The type or namespace name 'MyApp' could not be found (are you missing a using directive or an assembly reference?) 

Do you have an idea why this works with the Webforms view engine, but not with Razor? Is there any way to tell the compiler to use my dynamically loaded assembly for compilation?

thanks

+4
source share
2 answers

Where do you download your builds? Usually (as discussed in my blog here ), if you are not downloading your assemblies from the / bin directory, you need to make sure that the assembly path can be detected. The way I did it earlier is to use AppDomain.CurrentDomain.AppendPrivatePath(path) . Although this is an obsolete method, you do not create the AppDomain itself (the IIS workflow does this when it hosts your application), you can still use it to update the current domain for searching here. Now that the assembly is allowed, if it is not GAC'd, AppDomain will look in it for private paths for the assembly.

As to why it works for WebForms and not for Razor, we will need to learn more about your project architecture.

+2
source

I had a similar problem when compiling strongly typed views failed due to the inability to find the type. One solution is to create a custom assembly provider that inherits from RazorBuildProvider:

 public class CustomRazorBuildProvider : RazorBuildProvider { public override void GenerateCode(System.Web.Compilation.AssemblyBuilder assemblyBuilder) { Assembly a = Assembly.LoadFrom([PATH_TO_YOUR_ASSEMBLY]); assemblyBuilder.AddAssemblyReference(a); base.GenerateCode(assemblyBuilder); } 

}

Then you need to register this custom assembly provider with web.config:

 <compilation debug="true" targetFramework="4.0"> <assemblies> ... </assemblies> <buildProviders> <remove extension=".cshtml" /> <add extension=".cshtml" type="YouAssembly.CustomRazorBuildProvider, YourAssembly"/> </buildProviders> </compilation> 

This works, but the bad thing is that assemblies need to be referenced every time the view is compiled.

Here , I posted a question for a nicer solution (for example, it looks like AppDomain.CurrentDomain.AddPrivatePath), where you just specify the private path once, and this will be at the directory level, and not at the assembly level.

+1
source

Source: https://habr.com/ru/post/1344003/


All Articles