2010-03-08 24 views
10

Creé una aplicación simple ASP.NET MVC versión 1.0. Tengo un ProductController que tiene un índice de acción. En la vista, creé un Index.aspx correspondiente en la subcarpeta Producto.ASP.NET MVC View Engine Secuencia de resolución

Luego hice referencia al Spark dll y creé Index.spark en la misma carpeta de vista del Producto. El Application_Start parece

protected void Application_Start() 
    { 
     RegisterRoutes(RouteTable.Routes); 

     ViewEngines.Engines.Clear(); 
     ViewEngines.Engines.Add(new Spark.Web.Mvc.SparkViewFactory()); 

     ViewEngines.Engines.Add(new WebFormViewEngine()); 

    } 

Mi expectativa es que, dado que los registros del motor de encendido antes de WebFormViewEngine predeterminada, al navegar por la acción de índice en el controlador del producto, el motor de encendido se debe utilizar, y WebFormViewEngine se debe utilizar para todas las demás direcciones URL.

Sin embargo, la prueba muestra que la acción de índice para el controlador del producto también usa WebFormViewEngine.

Si comento el registro de WebFormViewEnginer (la última línea del código), puedo ver que la acción del índice es representada por el motor Spark y el resto de las URL genera un error (ya que el motor definitivo se ha ido), demuestra que todo mi código Spark es correcto.

Ahora mi pregunta es cómo se resuelve el motor de vista? ¿Por qué la secuencia de registro no tiene efecto?

Respuesta

18

El orden en que registra los motores de visualización no importa (mucho). Por el contrario, los motores de vista toman un conjunto de ViewLocationFormats, y si una ruta de vista particular se ajusta al nombre formateado, ese motor se utilizará. Solo si tiene formatos conflictivos, la orden de registro es importante.

En el caso de chispa, las vistas deben tener la extensión .spark. WebFormViewEngine responderá a cualquiera con extensiones .aspx o .ascx. Y, por supuesto, como se mencionó anteriormente, puede anular todo esto cambiando el ViewLocationFormats suministrado a los motores de vista individual.


Actualizado:

Me echó un vistazo a través de la fuente tanto de SparkViewFactory y WebFormViewEngine (o más específicamente, VirtualPathProviderViewEngine, que este último se deriva de), y puedo decir por qué estás viendo este extraño comportamiento.

En primer lugar, el método Find en la clase ViewEngineCollection funciona así (simplificado):

foreach (IViewEngine engine in Items) { 
    // Query engine for cached view 
} 

foreach (IViewEngine engine in Items) { 
    // Query engine for uncached view 
} 

En otras palabras, siempre va a tratar de encontrar una vista en caché, en cualquier motor, antes recurriendo al modo no en caché

La forma en que los motores de vista individuales implementan esto es la segunda sobrecarga del método FindView, que toma un argumento bool llamado useCache.

Sin embargo, y aquí es donde la cosa se pone raro - el VirtualPathProviderViewEngine y SparkViewEngine tienen ideas muy diferentes de lo que significa el argumento useCache.Hay demasiado código para volver a publicar aquí, pero la idea básica es:

  • El SparkViewFactory buscará única en la caché si es useCachetrue. Si no encuentra nada, automáticamente devuelve un "resultado de falta de caché", es decir, nada. Por otro lado, si useCache es false, no se verá en la memoria caché, omitirá el paso de comprobación de caché y realizará los movimientos normales para resolver y crear una vista real.

  • El VirtualPathProviderViewEngine, por el contrario, busca en la caché si es useCachetrue, y si no encuentra la vista en la memoria caché, sale y crea uno nuevo y añade que a la caché .

Ambos enfoques de trabajo con respecto a la forma en ViewEngineCollection lleva a cabo su búsqueda.

  • En el caso de la chispa, se "pierde" en la primera iteración de motores de vista, pero "éxitos" en la segunda, y después de que la vista se agrega a la caché. No hay problema.

  • En el caso de VirtualPathProviderViewEngine, "falla" internamente pero devuelve un "golpe" de todos modos en la primera iteración, momento en el que la vista se almacena en caché.

Así que debería poder ver dónde está el problema aquí. La única VirtualPathProviderViewEngine parece estar tomando precedencia sobre el SparkViewEngine porque el primero siempre tiene éxito en la primera iteración (caché), pero Spark tiene éxito solamente en la segunda iteración (sin caché).

En la llanura Inglés, Spark realmente pone preguntado primero, pero responde: "No, no tengo ese punto de vista todavía Pruébalo sin la memoria caché en su lugar.". WebForms se pregunta en segundo lugar, pero dice automáticamente "I no tengo esa vista, pero hice una para usted de todos modos, aquí está".. Y desde ese momento, el WebFormViewEngine siempre tiene prioridad porque tiene la vista almacenada en caché y Spark no.


Resumen: Spark es conseguir prioridad, pero debido a una peculiaridad en la forma de chispa trata el argumento useCache, se está haciendo dejó en el polvo cuando el motor de formularios Web está activo al mismo tiempo. O bien WebForm está demasiado ansioso o Spark es flojo, dependiendo de su perspectiva.

En pocas palabras, la solución es para no tener puntos de vista contradictorios. Si ha registrado varios motores de vistas, entonces debe tratar cualquier nombre de vista que pueda ser manejado por cualquiera de ellos/ambos como comportamiento indefinido.

+0

Resumiendo: Al eliminar el archivo Index.aspx se utilizará Index.spark. – LukLed

+0

Todavía no entiendo del todo. Los ViewLocationFormats se definen en VirtualPathProviderViewEngine, es una implementación interna específica para un motor de visualización. Si ASP.NET MVC tiene múltiples motores de vista registrados, consultará uno por uno para ver si un motor de vista puede manejar la solicitud. El primer motor de vista responde sí procesa la solicitud. En mi caso, tanto Spark como WebFormViewEngine pueden manejar la solicitud ya que Index.aspx e Index.spark están ahí. Entonces, ¿por qué WebForViewEngine siempre tiene prioridad? – intangible02

+0

@ intangible02: Probado y verificado, busqué en la fuente y ahora tengo una explicación para eso, eche un vistazo. – Aaronaught

1

Hmmm ... No, todos los formularios web de respeto no hacen nada más que una comprobación de caché cuando useCache es verdadero. Igual que Spark.

En realidad, creo que alguien podría haber movido mi queso ... Spark podría haber tenido una peculiaridad añadida que causó una falsa caché de falta durante el useCache == pase verdadero. Si eso es cierto, es más un error que diferentes reglas aplicadas a ese parámetro.


Actualizado:

que estaba viendo MVC 2 originalmente - por lo que he dado a entender @ conclusiones de Aaronaught no son correctos. MVC 2 no devuelve una vista en la primera pasada donde useCache == true, que es diferente en MVC 1.0, que se resolverá y rellenará.

Así que la diferencia está en la forma en que se implementan ASP.NET MVC 1.0 y ASP.NET MVC 2. Spark y MVC 2 tratan el flag useCache de la misma manera, y el orden en que están registrados les dará prioridad.

Cuestiones relacionadas