2013-05-02 11 views
5

Ich schreibe eine HtmlHelper Erweiterung und ich muss nach dem Vorhandensein einer Vorlage nach Name suchen. Die fragliche Vorlage kann je nach Kontext eine Anzeige oder eine Editor-Vorlage sein. Mein erster Gedanke war, ViewEngines.Engines.FindPartialView Methode zu verwenden. Es scheint jedoch, dass diese Methode die Verzeichnisse ~/Views/Shared/DisplayTemplates und ~/Views/Shared/EditorTemplates nicht durchsucht.
Ich nehme an, das ist aus gutem Grund. Wie würde die ViewEngine schließlich wissen, ob die Anzeige oder die Editor-Vorlage ohne zusätzliche kontextbezogene Informationen zurückgegeben wird?Finden Sie MVC Vorlage Ansicht nach Name

So führt, dass auf die Frage: Wie kann ich für eine bestimmte EditorTemplate suchen/DisplayTemplate Ich habe als eine benutzerdefinierte Ansicht Motor auf die ViewEngines Sammlung Hinzufügen dieser Standorte. Ich bin jedoch besorgt, dass dies problematisch sein könnte.

Meine größte Sorge ist, dass die DisplayTemplate/EditorTemplate Ansicht könnte für unbeabsichtigt etwas serviert werden. Sieht das jemand anders als ein Problem?
Ist es eine bessere Idee, nur eine bestimmte DisplayTemplateViewEngine/EditorTemplateViewEngine Instanz neu zu erstellen, wenn nötig und die ViewEngines Sammlung von dieser spezifischen Funktionalität freihalten?
Gibt es noch etwas, das mir fehlt?

Antwort

4

Ich liebe absolut, dass der MVC-Framework ist offen Quelle! Ich konnte anhand der TemplateHelpers-Klasse (innerhalb der MVC-Laufzeit) feststellen, dass der DataBoundControlMode beim Rendern einer Vorlage berücksichtigt wird. Die Antwort war einfach! Alles, was ich tun muss, ist den Template-Namen mit dem passenden Template-Director vorzuziehen. So, um eine Display-Vorlage zu finden:

var metadata = ModelMetadata.FromLambdaExpression(expression, HtmlHelper.ViewData); 
ViewEngines.Engines.FindPartialView(
    _controllerContext, 
    string.Format("DisplayTemplates/{0}", metadata.TemplateHint)) 

Keine zusätzlichen View-Engines oder Routing erforderlich! Wenn Sie an der Anwendung interessiert sind, generiert mein Helfer automatisch UI-Komponenten für ein bestimmtes Modell. Ich wollte das Vorhandensein einer benutzerdefinierten Vorlage aktivieren, um das automatisierte Rendering zu umgehen.

+0

Das ist die Antwort. Aber ich kann es für ein paar Tage nicht als solches bezeichnen. Es tut uns leid, wenn Sie sich für diesen Beitrag aufgrund seines offensichtlichen "unbeantworteten" Status interessiert haben. –

+0

Was ist metadata.TemplateHint oder woher kommt es? – xr280xr

+1

@ xr280xr: Aktualisiert, um die Metadaten-Definition einzuschließen. Hoffnung, die dir dienen! –

0

A WebFormViewEngine hat einige Eigenschaften, die Stellen definieren (Muster für) für Ansichten zu suchen.

Entweder folgen Sie der Konvention der View-Engine, die Sie verwenden, oder erstellen Sie eine benutzerdefinierte View-Engine (die z. B. Razor erweitert) mit benutzerdefinierten Ansichtspfaden.

Letzteres erklärt here:

public class CustomViewEngine : RazorViewEngine 
{ 
    public CustomViewEngine() 
    { 
     var viewLocations = new[] { 
      "~/Views/{1}/{0}.cshtml", 
      "~/Views/Shared/{0}.cshtml", 
      "~/Views/Shared/DisplayTemplates/{0}.cshtml", 
      "~/Views/Shared/DisplayTemplates/{1}/{0}.cshtml", 
      // etc 
     }; 

     this.PartialViewLocationFormats = viewLocations; 
     this.ViewLocationFormats = viewLocations; 
    } 
} 

Also ich in Ihrem Helfer erraten sollten Sie die aktuelle Ansicht Motor nachzuschlagen und seine Sicht Standortpfade suchen und sie in Reihenfolge. Hat ein HTML-Helfer keine Methode oder Eigenschaft zum Abrufen der Ansicht, in der Sie gerade ausgeführt werden?

+0

Danke für die Antwort. Ich bin eigentlich nicht gegen die Konvention; Meine Struktur entspricht den erwarteten MVC-Architekturdefinitionen.Das Problem besteht darin, dass die FindPartialView-Methode der ViewEnginesCollection nicht nach diesen Speicherorten sucht, da sie nicht wissen würde, ob Sie die Anzeige- oder Editorversion verwenden möchten. Ich habe jedoch eine Lösung gefunden. Siehe meine Antwort als Referenz. Danke noch einmal. –

+0

1) Ist der Code in Ihrem Beispiel das Standard-Razor-Verhalten? 2) Worauf beziehen sich '{0}' und '{1}'? – Shimmy

+0

@Shimmy [Dies ist die Standardeinstellung] (https://github.com/ASP-NET-MVC/aspnetwebstack/blob/master/src/System.Web.Mvc/RazorViewEngine.cs). Die Ersatzwerte lauten '{0}' = Name der Ansicht, '{1}' = Name des Controllers und '{2}' = Name des Bereichs (siehe ['ViewLocation' und' AreaAwareViewLocation' am Ende dieser Datei] (https: //github.com/ASP-NET-MVC/aspnetwebstack/blob/4e40cdef9c8a8226685f95ef03b746bc8322aa92/src/System.Web.Mvc/VirtualPathProviderViewEngine.cs)). – CodeCaster

0

Warum bilden Sie nur den relativen Pfad

string path = Server.MapPath("~/View/"); 

Und dann überprüfen, ob die Datei Ausfahrten Basis auf dem .cshtml Ausgang des in diesem speziellen Verzeichnis

string fileName = "MyView.cshtml"; 
if (File.Exists(path + fileName)) 
    //do somethings 
else 
    //do another things 
+0

Ein Vorteil der Verwendung der ViewEngine ist, dass sie verspottet werden kann, um sie testbar zu machen. Diese Lösung ist sehr schwierig zu testen. Froh für Ihre Eingabe, obwohl! –