Строго типизированные представления Razor в динамически загружаемой сборке не компилируются во время выполнения - PullRequest
4 голосов
/ 16 марта 2011

У меня есть область MVC3 в сборке, которая динамически загружается с MEF.
Если я использую движок представлений Webforms со строго типизированными представлениями, все работает нормально.
Если я использую движок Razor view с моделью dynamic, он тоже работает нормально.

Но если я использую строго типизированное представление Razor , компиляция представления завершится неудачей во время выполнения.

Проблема в том, что динамически загруженная сборка отсутствует в списке сборок, на которые имеются ссылки, которые передаются компилятору C #.

Сгенерированный код C # выглядит следующим образом:

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

А вот и сообщение об ошибке:

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

Есть ли у вас идеи, почему это работает с движком представления Webforms, но не с Razor? Есть ли способ сказать компилятору использовать мою динамически загруженную сборку для компиляции?

Спасибо

Ответы [ 2 ]

2 голосов
/ 27 ноября 2011

У меня была похожая проблема, когда компиляция строго типизированных представлений не удалась из-за невозможности найти тип.Одним из решений является создание настраиваемого поставщика сборки, который наследуется от 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);
  }

}

Затем необходимо зарегистрировать этого настраиваемого поставщика сборки в web.config:

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

Это работает, но плохо то, что на сборки нужно ссылаться каждый раз, когда компилируется представление.

Здесь , я разместил вопрос о более удачном решении (например, похожем на AppDomain.CurrentDomain.AddPrivatePath), где вы просто указали бы частный путь один раз, и он был бы на уровне каталогане на уровне сборки.

2 голосов
/ 17 марта 2011

Откуда вы загружаете свои сборки? Обычно (как обсуждалось в моем блоге здесь ), если вы не загружаете свои сборки из каталога / bin, вам необходимо убедиться, что путь к сборкам доступен для обнаружения. Способ, которым я сделал это ранее, заключается в использовании AppDomain.CurrentDomain.AppendPrivatePath(path). Хотя это устаревший метод, вы сами не создаете домен AppDomain (рабочий процесс IIS делает это, когда он размещает ваше приложение), вы все равно можете использовать его для обновления текущего домена для поиска здесь. Теперь, когда сборка разрешается, если это не GAC, AppDomain будет искать в своих личных путях сборку.

Что касается того, почему он работает для WebForms, а не для Razor, нам нужно больше узнать об архитектуре вашего проекта.

...