类库中的MEF和Razor视图

And*_*tos 28 asp.net-mvc virtualpathprovider embedded-resource razor asp.net-mvc-3

我有一个使用MEF的复合ASP .NET MVC 3 Razor应用程序.如果我要Views在应用程序的常规文件夹下部署插件作为DLL文件和视图(CSHTML),一切都会好起来的.但这不是很干净,如果我不将视图作为嵌入式资源放在DLL文件中(以及控制器和模型),它将不是真正的插件.

我跟着很多文章(其中大部分都已过时).事实上,Stack Overflow上有一个非常好的:类库中的控制器和视图

我还检查了文档VirtualPathProvider,我已经能够构建一个自定义文件,在程序集中找到该文件并完美加载它(或至少获取它的流).为此,我遵循了VirtualPathProvider MSDN上文档.

VirtualFile还有一个实现,但VirtualDirectory尚未实现.

这是问题所在.我正在使用Razor的观点.我知道他们需要web.configRazor文件中的配置规范来构建它们.但是如果我将它们嵌入到DLL中,那么这个配置就会丢失.

我想知道这是不是我继续得到错误的原因:

'〜/ Plugins/CRM.Web.Views.CRM.Index.cshtml'中的视图必须从WebViewPage或WebViewPage派生.

也许我只需要添加一些代码来使它工作?有任何想法吗?

sky*_*dev 7

在类库中嵌入Razor Views的首选方法是使用post build事件将它们复制到MVC网站的Views/Areas文件夹中.如果覆盖ViewEngine或VirtualPathProvider,则可以指定自定义视图位置.

对我来说棘手的部分是让intellisense在这些View类库中工作.首先,您必须将Web.Config添加到View程序集.请注意,您不必将其实际包含在程序集中.它只需要在程序集根目录(或视图文件夹)中.这是一个例子.关注重要的Assemblies/Compilation部分.

<?xml version="1.0"?>
<configuration>
  <configSections>
    <sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
      <section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
      <section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
    </sectionGroup>
  </configSections>

  <system.web.webPages.razor>
    <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
    <pages pageBaseType="System.Web.Mvc.WebViewPage">
      <namespaces>
        <add namespace="System.Web.Mvc" />
        <add namespace="System.Web.Mvc.Ajax" />
        <add namespace="System.Web.Mvc.Html" />
        <add namespace="System.Web.Routing" />
      </namespaces>
    </pages>
  </system.web.webPages.razor>

  <appSettings>
    <add key="webpages:Enabled" value="false" />
  </appSettings>

  <system.web>
    <compilation targetFramework="4.0">
      <assemblies>
        <add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
        <add assembly="System.Web.Routing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
        <add assembly="System.Data.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
        <add assembly="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
        <add assembly="System.Web.WebPages, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
      </assemblies>
    </compilation>

    <httpHandlers>
      <add path="*" verb="*" type="System.Web.HttpNotFoundHandler"/>
    </httpHandlers>

    <!--
        Enabling request validation in view pages would cause validation to occur
        after the input has already been processed by the controller. By default
        MVC performs request validation before a controller processes the input.
        To change this behavior apply the ValidateInputAttribute to a
        controller or action.
    -->
    <pages
        validateRequest="false"
        pageParserFilterType="System.Web.Mvc.ViewTypeParserFilter, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
        pageBaseType="System.Web.Mvc.ViewPage, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
        userControlBaseType="System.Web.Mvc.ViewUserControl, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
      <controls>
        <add assembly="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" namespace="System.Web.Mvc" tagPrefix="mvc" />
      </controls>
    </pages>
  </system.web>
  <system.webServer>
    <validation validateIntegratedModeConfiguration="false" />
    <handlers>
      <remove name="BlockViewHandler"/>
      <add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler" />
    </handlers>
  </system.webServer>
</configuration>
Run Code Online (Sandbox Code Playgroud)

接下来,您需要修改类库的vbproj文件,以便所有OutputPath元素指向'bin \'而不是'Debug\bin \'或'Release\bin \'.这是我在类库和ASP.Net Web项目类型之间发现的主要区别,它们可能导致智能感知错误.

如果仍然收到必须继承的错误,请考虑在视图中使用@Inherits System.Web.Mvc.WebViewPage.如果您没有将视图复制到网站项目中,则可以使用自定义ViewEngine/VirtualPathProvider从嵌入式资源加载它们.如果是这种情况,你肯定需要继承,所以Razor不幸地知道你的视图基类.

祝好运.