2010-03-08 9 views
10

Ich habe eine einfache ASP.NET MVC Version 1.0-Anwendung erstellt. Ich habe einen ProductController, der einen Aktionsindex hat. In der Ansicht habe ich eine entsprechende Index.aspx unter Produkt Unterordner erstellt.ASP.NET MVC View Engine Auflösung Sequenz

Dann referenziert ich die Spark dll und erstellt Index.spark unter dem gleichen Produkt-Ansicht-Ordner. Die Application_Start sieht aus wie

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

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

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

    } 

Meine Erwartung ist, dass, da die Spark-Motor Register vor Default WebFormViewEngine, wenn der Index Aktion in Produkt Controller zu finden, sollte der Spark-Motor verwendet werden, und WebFormViewEngine sollte für alle anderen URLs verwendet werden.

Der Test zeigt jedoch, dass die Aktion Index für Product Controller auch die WebFormViewEngine verwendet.

Wenn ich die Registrierung von WebFormViewEnginer (die letzte Zeile im Code) auskommentieren, kann ich sehen, dass die Aktion Index von Spark Engine gerendert wird und der Rest URLs generiert einen Fehler (seit die defualt Engine ist weg), es beweist, dass mein Spark-Code korrekt ist.

Jetzt ist meine Frage, wie die View Engine gelöst ist? Warum wird die Registrierungssequenz nicht wirksam?

Antwort

18

Die Reihenfolge, in der Sie die View-Engines registrieren, spielt keine Rolle (viel). View Engines nehmen stattdessen eine Menge von ViewLocationFormats, und wenn ein bestimmter Ansichtspfad den formatierten Namen passt, wird diese Engine verwendet. Nur wenn Sie widersprüchliche Formate haben, ist der Registrierungsauftrag wichtig.

Im Fall von Funken sollten Ansichten die Erweiterung .spark haben. WebFormViewEngine reagiert auf alle mit .aspx oder .ascx Erweiterungen. Und natürlich, wie oben erwähnt, können Sie dies durch Ändern der ViewLocationFormats, die den einzelnen View-Engines zur Verfügung gestellt wird, überschreiben.


Aktualisiert:

Ich nahm einen Blick durch die Quelle sowohl SparkViewFactory und WebFormViewEngine (oder genauer gesagt, VirtualPathProviderViewEngine, die dieser ergibt sich aus), und ich kann Ihnen sagen, warum du bist dieses seltsame Verhalten sehen.

Vor allem der Find Methode in der ViewEngineCollection Klasse funktioniert wie folgt (vereinfachte):

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

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

Mit anderen Worten, es wird immer versuchen, eine zwischengespeicherte Ansicht zu finden, in jeden Motor vor Zurückgreifen auf nicht-cached-Modus.

Die Art und Weise, in der einzelne View-Engines dies implementieren, ist die zweite Überladung der FindView-Methode, die ein bool-Argument namens useCache verwendet.

jedoch, und hier ist, wo alles seltsam bekommt - die VirtualPathProviderViewEngine und SparkViewEngine haben sehr unterschiedliche Vorstellungen davon, was das useCache Argument bedeutet.Es gibt zu viel Code hier umbuchen, aber die Grundidee ist:

  • Die SparkViewFactorynur im Cache aussehen wird, wenn useCachetrue ist. Wenn es nichts findet, gibt es automatisch ein "Cache-Miss-Ergebnis" zurück - d. H. Nichts. Auf der anderen Seite, wenn useCachefalse ist, wird es überhaupt nicht in den Cache schauen, es wird den Cache-Überprüfungsschritt überspringen und die normalen Bewegungen durchlaufen, um eine tatsächliche Ansicht aufzulösen und zu erstellen.

  • Die VirtualPathProviderViewEngine, auf der anderen Seite, sieht in dem Cache, wenn useCachetrue ist, und wenn es nicht die Ansicht im Cache findet, es erlischt und ein neues erstellt und fügt hinzu, dass in den Cache .

Beide Ansätze funktionieren in Bezug auf die Art und Weise ViewEngineCollection seine Suche durchführt.

  • Im Fall des Funken, es „Misses“ auf der ersten Iteration der Ansicht Motoren, sondern „Hits“ auf dem zweiten und nach, dass die Sicht auf den Cache hinzugefügt wird. Kein Problem.

  • Im Fall von VirtualPathProviderViewEngine "intern" fehlschlägt es "aber" gibt in der ersten Iteration trotzdem einen "Treffer" zurück, zu welchem ​​Zeitpunkt die Ansicht jetzt zwischengespeichert wird.

So sollten Sie in der Lage sein zu sehen, wo das Problem hier ist. Die VirtualPathProviderViewEngine nur erscheint Vorrang vor den SparkViewEngine nehmen, weil die ehemaligen gelingt es immer wieder auf der ersten (gecached) Iteration, aber Funken nur auf der zweite (uncached) Iteration erfolgreich ist.

In einfachem Englisch, Funke wirklich zuerst aufgetaucht ist, aber antwortet: „Nein, ich habe diese Ansicht nicht noch anstatt sie ohne Cache versuchen..“ WebForms wird gefragt, aber sagt automatisch "Ich habe nicht haben diese Ansicht, aber ich ging und machte eine für Sie sowieso, hier ist es.". Und von diesem Punkt an erhält die WebFormViewEngine immer Priorität, weil sie die Ansicht zwischengespeichert hat und Spark nicht.


Zusammenfassung: Funken sind immer Priorität, aber wegen einer Marotte in der Art und Weise Funken behandeln das useCache Argument, es links in dem Staub zu werden, wenn die Web-Formular-Engine zur gleichen Zeit aktiv ist. Entweder WebForm ist übereifrig oder Spark ist faul, abhängig von Ihrer Perspektive.

Einfach gesagt, ist die Lösung keine widersprüchlichen Ansichten zu haben! Wenn Sie mehrere View-Engines registriert haben, sollten Sie jeden Ansichtsnamen behandeln, der von beiden als undefined Verhalten behandelt werden kann.

+0

Zusammenfassend: Entfernen von Index.aspx Datei wird Index.spark verwendet. – LukLed

+0

verstehe ich immer noch nicht ganz. Das ViewLocationFormats ist in VirtualPathProviderViewEngine definiert und ist eine interne Implementierung, die für eine View-Engine spezifisch ist. Wenn der ASP.NET MVC mehrere View-Engines registriert hat, fragt er nacheinander ab, ob eine View-Engine die Anforderung verarbeiten kann. Die erste View-Engine antwortet mit yes, um die Anfrage zu bearbeiten. In meinem Fall können Spark und WebFormViewEngine die Anforderung verarbeiten, da Index.aspx und Index.spark vorhanden sind. Warum hat WebForViewEngine immer Vorrang? – intangible02

+0

@ intadible02: Getestet und verifiziert, habe ich die Quelle durchforstet und habe jetzt eine Erklärung dafür, schau mal. – Aaronaught

1

Hmmm ... Nein - alles in allem Webforms tut nichts über eine Cache-Prüfung hinaus, wenn UseCache wahr ist. Genau wie Spark.

Eigentlich - ich denke, jemand könnte meinen Käse bewegt haben ... Spark könnte eine Eigenart hinzugefügt haben verursacht einen falschen Cache-Miss während der VerwendungCache == True Pass. Wenn das wahr ist, ist es eher ein Fehler als verschiedene Regeln, die auf diesen Parameter angewendet werden.


Aktualisiert:

ich MVC 2 ursprünglich Suche wurde - weshalb ich implizierten @ Aaronaught Schlussfolgerungen falsch waren. MVC 2 gibt keine Sicht auf den ersten Durchlauf zurück, wo useCache == true ist, was in MVC 1.0 anders ist, das auflösen und auffüllen wird.

So ist der Unterschied zwischen der Art, wie ASP.NET MVC 1.0 und ASP.NET MVC 2 implementiert sind. Spark und MVC 2 behandeln das useCache-Flag gleich, und die Reihenfolge, in der sie registriert sind, gibt ihnen Priorität.