Estoy usando vistas compiladas Razor en bibliotecas de clases separadas como una especie de sistema de complemento para MVC3.MVC3 - Vista de navaja compilada no se puede encontrar _ViewStart
He seguido la guía de Chris Van De Steed here y solo me he desviado principalmente en la parte sobre cómo agregar referencias, ya que estoy cargando mis ensamblajes en tiempo de ejecución.
Debido a que estoy cargando ensamblajes en tiempo de ejecución, no estoy usando VirtualPathProviderViewEngine en la biblioteca de BoC, y en su lugar implementé mi propio ViewEngine basado en RazorViewEngine. Funciona reescribiendo el viewPath en CreateView para insertar el espacio de nombre apropiado para que la vista se pueda resolver.
Hasta ahora todo bien ... Puedo cargar diferentes módulos y sus controladores no colisionarán si comparten el mismo nombre.
El único problema que tengo ahora es que para las vistas compiladas, no se llama al _ViewStart. _ViewStart funciona para vistas en el proyecto host MVC3, pero para las vistas cargadas desde los ensamblados de complementos no se encuentra.
Tengo una configuración de ruta de esta manera: -
RouteTable.Routes.MapRoute(
string.Format("Plugin{0}Route", pluginName),
string.Format(@"Plugin/{0}/{{controller}}/{{action}}", pluginName),
new { },
new string[] { string.Format("{0}.Controllers", pluginName) });
la ViewEngine se ve así: -
public class PluginRazorViewEngine : RazorViewEngine
{
public PluginRazorViewEngine() : base()
{
ViewLocationFormats = new[]
{
"~/Plugin/%1/Views/{1}/{0}.cshtml",
"~/Plugin/%1/Views/{1}/{0}.vbhtml",
"~/Plugin/%1/Views/Shared/{0}.cshtml",
"~/Plugin/%1/Views/Shared/{0}.vbhtml",
"~/Views/{1}/{0}.cshtml",
"~/Views/{1}/{0}.vbhtml",
"~/Views/Shared/{0}.cshtml",
"~/Views/Shared/{0}.vbhtml"
};
(el% 1 se sustituye por el nombre de la asamblea)
y el conjunto está registrado en la biblioteca de BoC así: -
BoC.Web.Mvc.PrecompiledViews.ApplicationPartRegistry.Register(assembly, string.Format("/Plugin/{0}/", pluginName));
Cuando la vista se carga desde un ensamblaje de complemento (en este ejemplo "cuentas"), la vista se encuentra y se muestra en Aceptar. Pero entonces se ve en estas ubicaciones para el _ViewStart: -
~/plugin/accounts/views/invoice/_viewstart.cshtml
~/plugin/accounts/views/invoice/_viewstart.vbhtml
~/plugin/accounts/views/_viewstart.cshtml
~/plugin/accounts/views/_viewstart.vbhtml
~/plugin/accounts/_viewstart.cshtml
~/plugin/accounts/_viewstart.vbhtml
~/plugin/_viewstart.cshtml
~/plugin/_viewstart.vbhtml
~/_viewstart.cshtml
~/_viewstart.vbhtml
pero no se ve en ~/Vistas/Común/_ViewStart.cshtml donde vive el archivo.
He intentado cambiar todos los formatos de localización en mi ViewEngine (AreaMasterLocationFormats, AreaPartialViewLocationFormats, AreaViewLocationFormats, MasterLocationFormats, PartialViewLocationFormats y ViewLocationFormats) pero ninguno de ellos parecen hacer una diferencia.
He mirado alrededor y parece que System.Web.WebPages.StartPage.GetStartPage es responsable de encontrar y devolver la página de inicio en una vista, pero no puedo encontrar ninguna información sobre cómo controlar dónde se ve.
He intentado mover el _ViewStart.cshtml a ~/_ViewStart.cshtml (uno de los lugares que se ve) sin embargo obtener de inmediato: -
Unable to cast object of type 'ASP._Page__ViewStart_cshtml' to type 'System.Web.WebPages.StartPage'.
que según lo que he leído, es porque _ViewStart necesita vivir en/Vistas
¿Puedo modificar dónde MVC busca un _ViewStart?
La biblioteca del Banco de Canadá implementa su propio IView, y llama a los siguientes: -
startPage = this.StartPageLookup(page, VirtualPathFactoryManagerViewEngine.ViewStartFileName, this.ViewStartFileExtensions);
Pero en este caso es sólo ViewStartFileName "_ViewStart" y ViewStartFileExtensions son sólo cshtml y vbhtml ... nada que pueda controlar dónde MVC debería buscar el archivo.
Hice como sugirió y creé mi propio "PluginRazorView" heredando de RazorView. Tuve que anular RenderView como sugirió e intenté replicar lo que hace el método MVC GetStartPage y simplemente agregar mi propia lógica para buscar las rutas adicionales, sin embargo, es un campo minado de internos y reflexión así que he pirateado algo para demostrar que funciona y tendré que limpiarlo más tarde. Es interesante que hayan usado un delegado aquí ... parece que se pueden usar diferentes métodos de búsqueda, pero no hay forma de especificarlos. Muchas gracias por la ayuda. – Aleks
Sí, eso es lo que pensé también. Como dices, usan un delegado para permitir el cambio del método de búsqueda, pero luego lo declaran 'interno', por lo que solo el espacio de nombres de Mvc puede cambiarlo ... – JimmiTh