Strongly typed Razor views in dynamically loaded assembly don't compile at runtime

一世执手 提交于 2020-01-03 17:07:25

问题


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

But if I use a strongly typed Razor view, the view compilation fail at runtime.

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

The generated C# code looks like this:

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 any idea why this works with the Webforms view engine but not with Razor ? Is there a way to tell the compiler to use my dynamically loaded assembly for the compilation ?

Thanks


回答1:


I had the similar problem, when compilation of strongly typed views fails due to not being able to find the type. One solution is to create custom build 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 build provider in web.config:

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

It works, but the bad thing is that assemblies need to be referenced everytime the view is compiled.

Here, I have posted a question for a nicer solution (for example similar to AppDomain.CurrentDomain.AddPrivatePath) where you would just specify private path once, and it would be on directory level, not on assembly level.




回答2:


Where are you loading your assemblies from? Typically (as discussed on my blog here) if you are not loading your assemblies from the /bin directory, you need to ensure that the path to the assemblies is discoverable. The way I've done this previously is to use AppDomain.CurrentDomain.AppendPrivatePath(path). Although this is a deprecated method, you're not constructing the AppDomain youself (the IIS worker process does this when it hosts your app), you can still use it to update the current domain to search here. Now when an assembly is being resolved, if its not GAC'd, the AppDomain will search it's private paths for the assembly.

As to why it works for WebForms as opposed to Razor, we'd need to know more about your project architecture.



来源:https://stackoverflow.com/questions/5331591/strongly-typed-razor-views-in-dynamically-loaded-assembly-dont-compile-at-runti

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!