tag net for asp asp.net-mvc asp.net-mvc-3 razor embedded-resource virtualpathprovider

asp.net-mvc - for - tag helper asp net core 2



Vistas de MEF y Razor dentro de la Biblioteca de clases (4)

Hossam,

La publicación de la que estás hablando es lo que Darin ya ha sugerido. La desventaja principal de ese enfoque es usar el compilador personalizado MvcRazorClassGenerator para convertir los archivos de vista CSHTML en archivos de clase. Para hacerlo, debe establecer cada vista CSHTML en su proyecto en Contenido y configurar la Herramienta personalizada en MvcRazorClassGenerator.

No puedo hablar por LordALMMa, pero descargué la fuente del compilador y le di una oportunidad, y no funciona exactamente como esperaba.

Mi otro enfoque fue incluir los archivos CSHTML como recursos incrustados en la DLL externa, leer los contenidos sin formato del archivo y ejecutar la vista como una cadena (consulte RazorEngine en CodeProject para obtener un ejemplo: http://razorengine.codeplex.com/ )

No quería depender completamente del RazorEngine en una aplicación empresarial porque no sé si es compatible con toda la sintaxis de Razor, así que desistí de eso por el momento.

Vengo de un prototipo que construí en ASP.NET MVC 2.0 que es una aplicación multi-tennant. En una granja de servidores, tenemos una instancia de una aplicación que se ejecuta donde todos los clientes comparten la misma base de código. En mi prototipo MVC 2.0, pude determinar para qué "cliente" se estaba haciendo la solicitud, buscar un controlador personalizado que sobrepasara la base (para personalizaciones del código central) y también buscar vistas personalizadas (para personalizaciones de la vista del núcleo). Lo que esto hace es permitirnos implementar un "complemento" por cada cliente. El software detecta si el cliente tiene un controlador personalizado que coincida con la solicitud, así como una acción personalizada que coincida y si lo hace, utiliza el controlador / acción personalizada en su lugar.

Cuando comencé a migrar mi prototipo a MVC 3, corrí al mismo problema que a LordALMMa, el error "La vista en ''... Index.cshtml'' debe derivarse de WebViewPage o WebViewPage". Buscaré la ubicación de "@inherits System.Web.Mvc.WebViewPage" en mis vistas CSHTML y veré si eso me acerca más a que funcione.

Dado que tengo un prototipo MVC 2.0 que funciona con MVC 3 Razor no es una prioridad y no desperdicio mucho tiempo en ello. Estoy seguro de que puedo portar el MVC 2.0 a MVC 3.0 utilizando el motor de WebForms si necesitamos aprovechar el Marco 4.0.

Tengo una aplicación compuesta ASP.NET MVC 3 Razor usando MEF. Todo va bien si tengo que implementar complementos como archivos DLL y vistas (CSHTML) en la carpeta de Views normal desde la aplicación. Pero esto no es muy limpio y no será un complemento real si no coloco las vistas como recursos incrustados dentro de los archivos DLL (junto con los controladores y los modelos).

He seguido muchos artículos (la mayoría de ellos están desactualizados). De hecho, hay uno muy bueno aquí en Stack Overflow: Controladores y Vistas dentro de una Biblioteca de Clases

También revisé documentos para VirtualPathProvider y pude crear uno personalizado que encuentra el archivo dentro del ensamblaje y lo carga perfectamente (o al menos obtiene la transmisión). Para esto, he seguido la documentación de VirtualPathProvider en MSDN .

También hay una implementación para VirtualFile pero aún no para VirtualDirectory.

Aquí está el problema Estoy trabajando con vistas de Razor. Sé que necesitan especificaciones de configuración del archivo web.config para que Razor las construya. Pero si los incrusto dentro de la DLL, esta configuración simplemente se pierde.

Me pregunto si es por eso que sigo recibiendo el error:

La vista en ''~ / Plugins / CRM.Web.Views.CRM.Index.cshtml'' debe derivarse de WebViewPage o WebViewPage.

¿Tal vez solo necesito agregar un código para que funcione? ¿Algunas ideas?


Mi forma preferida de incrustar Razor Views en una Class Library es copiarlos en las carpetas Views / Areas del sitio web de MVC con un evento post build. Se pueden especificar ubicaciones de vista personalizadas si anula ViewEngine o VirtualPathProvider.

La parte más difícil para mí fue hacer que intellisense funcionara en estas bibliotecas de View Class. Primero, debe agregar un Web.Config a su ensamblaje de Vista. Tenga en cuenta que no tiene que incluirlo en su conjunto. Solo tiene que estar en el directorio raíz del ensamblaje (o en la carpeta de vistas). Aquí hay un ejemplo. Consulte la sección de ensamblajes / compilación importante.

<?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>

A continuación, debe modificar el archivo vbproj de la biblioteca de su clase para que todos los elementos de OutputPath apunten a ''bin /' en lugar de ''Debug / bin /' o ''Release / bin /'. Esta es la principal diferencia que encontré entre las bibliotecas de clases y los tipos de proyectos web ASP.Net que pueden causar errores intellisense.

Si aún recibe su error debe heredar, considere usar @Inherits System.Web.Mvc.WebViewPage en sus vistas. Si no está copiando sus vistas en el proyecto de su sitio web, puede que las esté cargando desde Embedded Resources utilizando un ViewEngine / VirtualPathProvider personalizado. Si ese es el caso, definitivamente necesitas las Heredades para que Razor sepa cuál es desafortunadamente tu clase de base de vistas.

Buena suerte.


Oye, sospecho que tienes buenos motivos para querer vistas dentro de las DLL. Sin embargo, también considere que es una forma inusual de empaquetar todo en una sola entidad.

Si está desarrollando un complemento, en la actualidad las personas optan por el empaque en el formato NUGET, que también resuelve su tipo de problema, entre otras cosas. Tiene una estructura .nupkg que también es una forma de distribuir complementos como paquetes y bibliotecas.

Otra solución que las comunidades generalmente siguen (si no quieren algo tan complejo como Nuget) codifican las DLL de los complementos de manera que no utiliza motores de vista como la navaja de afeitar, sino que emite HTML por sí mismo utilizando la antigua forma primitiva de Respuesta .Escribir y, por lo tanto, ser independiente de los archivos cshtml. Si aún desea usar cshtml, consulte esta entrada en el blog para precompilarlos en clases.