2

Ich stelle gerade eine Multi-Tenancy-Webanwendung mit MVC 3 zusammen. Mindestens 30 verschiedene Websites teilen sich eine gemeinsame Codebasis und teilen sie auch ähnlich Under-the-hood-Funktionalität müssen sie deutlich anders aussehen. Daher verwende ich die URL, um Clients intern zu trennen, und eine überschriebene Razor-Ansichts-Engine (um die Ansicht zu finden), um automatisch entweder eine benutzerdefinierte Ansicht für eine bestimmte Aktion oder die Standardansicht auszuwählen.Ausgewählten Ansichtspfad als HTML-Kommentar eingeben, um die Ausgabe der Aktion zu starten und zu beenden

Um eine komplexe Seite zu kompartimentieren, verwendet eine bestimmte Ansicht mehrere Teiltabellen, die normalerweise als eigenständige Aktionen gerendert werden, sodass eine benutzerdefinierte Ansicht oder Teilansicht im Allgemeinen nur kleine HTML-Unterschiede aufweist beliebiger Code, der für die Site eines Kunden spezifisch ist.

Ich hoffe, Sie sind diesem Hintergrund gefolgt!

Eine HTML-Seite könnte also aus vielen kleinen Teilen von HTML-Teilansichten bestehen, die aus bestimmten Ordnern für den Client stammen könnten, oder aus einer allgemeinen Version. Ich hoffe, es unserem Designer leichter zu machen, kleinere Änderungen an einer Seite vorzunehmen, indem wo in der Ordnerstruktur das bisschen HTML angezeigt wird, das er ändern möchte.

Mein Vorschlag ist dann, dass jeder Teil mit HTML-Kommentaren wie ‚eingeklammert‘ wird: nur

{Inhalt des Teils}

Offensichtlich ich diese manuell setzen könnte, aber das ist nach Problemen fragen, nach Tippfehlern, nach kopierten und dann geänderten Clientversionen, die nicht mit der richtigen URL aktualisiert werden. Es sollte möglich sein, dies aus irgendeinem Kontext zu bekommen und es zu injizieren, denke ich.

Gleichzeitig muss ich dies für bestimmte Aktionen nicht tun können. Zum Beispiel könnte ein Teil Text in einem Textarea erzeugen, sagen wir, so dass die Kommentare dort nicht angebracht wären. Im Großen und Ganzen bin ich glücklich, diese Kommentare in setzen, es sei denn Ich gebe an, dass es nicht angemessen ist.

Für mich schlägt dies einen ActionFilter auf einer Aktion vor, die ich Site-weit anwenden kann und dann für bestimmte Aktionen ausschalte. Ich hoffe, dass mich eines der überstürzbaren Ereignisse diesen Weg ermitteln lässt, aber ich kann nirgends finden, wo er gespeichert ist. Darüber hinaus scheint OnResultExecuting ausgelöst zu werden, bevor Partial ausgewählt wurde, und OnResultExecuted scheint den Inhalt von Partial bereits ausgeschrieben zu haben, weshalb ich den Anfangskommentar hier nicht einfügen kann. Ich kann auch keinen Bezug zum Pfad des ausgewählten Teils finden.

Nur der Vollständigkeit halber ist es meine Absicht, dass dieses Attribut nur diese Kommentare schreiben würde, wenn im Debug-Modus kompiliert.

Also weiß jemand, wie ich den Pfad zu der ausgewählten Ansicht ohne jede Art von Hack zwischen FindPartialView und dem Attribut erhalten könnte? Ist meine Attributmethode die beste Wahl oder gibt es einen einfacheren Weg dazu? Vielleicht ist schon etwas eingebaut!

Vielen Dank für Ihre Hilfe.

Antwort

0

Nun, ich habe nie vergessen, dies zu wollen, und immer gehofft, ich würde es eines Tages lösen, und zum Glück habe ich.

ich die Standard-WebViewPage außer Kraft gesetzt habe (ich benutze das Razor-Motor), insbesondere ExecutePageHierarchy die Kommentare zu injizieren:

public abstract class PaladinWebViewPage : PaladinWebViewPage<dynamic> 
{ 
} 

public abstract class PaladinWebViewPage<TModel> : WebViewPage<TModel> 
{ 
    public bool DisplaySourceCodeComments 
    { 
     get { return ((bool?) ViewBag.__DisplaySourceCodeComments) ?? false; } 
     set { ViewBag.__DisplaySourceCodeComments = value; } 
    } 

    public override void ExecutePageHierarchy() 
    { 
     base.ExecutePageHierarchy(); 

     // Filters can be used to set and clear this value so we can decide when to show this comment 
     if (!DisplaySourceCodeComments) return; 

     var sw = Output as StringWriter; 
     if (sw == null) return; 

     var sb = sw.GetStringBuilder(); 
     sb.Insert(0, string.Format("<!-- Start of {0} -->", VirtualPath)); 
     sb.AppendFormat("<!-- End of {0} -->", VirtualPath); 
    } 

VirtualPath uns die genaue Datei die HTML zu bauen verwendet erzählt, so können wir injiziere den Dateinamen vorher und nachher. Dies tut im Moment nichts, da der Standardwert nicht Kommentare anzeigen (das "?? False" in DisplaySourceCodeComments).

Um diese Ansichtsseite zu verwenden, müssen Sie Views/Web.config bearbeiten und den pageBaseType auf diesen Typ ändern.

Ich möchte selektiv diese Kommentare ein- und ausschalten, so habe ich eine Action erstellt:

public class DisplaySourceCodeCommentsAttribute : ActionFilterAttribute 
{ 
    private readonly bool _displaceSourceCodeComments; 

    public DisplaySourceCodeCommentsAttribute(bool displaceSourceCodeComments) 
    { 
     _displaceSourceCodeComments = displaceSourceCodeComments; 
    } 

    public override void OnActionExecuted(ActionExecutedContext filterContext) 
    { 
     base.OnActionExecuted(filterContext); 

     var viewResult = filterContext.Result as ViewResultBase; 
     if (viewResult == null) return; 

     viewResult.ViewBag.__DisplaySourceCodeComments = _displaceSourceCodeComments; 
    } 
} 

Ich bin ein wenig unglücklich, dass ich die ViewBag hätte hier zu verwenden und auch separat in der Ansicht Seitenüberschreibung, da sie nicht eng miteinander verknüpft sind, aber ich finde keinen Weg für den Filter, direkt mit der Ansichtsseite zu interagieren, also ist das etwas von einem notwendigen Fudge. Es hat den Vorteil, dass das Anzeigen von Quellcode für eine Ansicht oder teilweise auch automatisch für alle untergeordneten Teiltabellen angezeigt wird, bis Sie sie wieder ausschalten, da der ViewBag in der Kette weitergegeben wird.

In diesem Ort kann jede Aktion auf dem Quellcode drehen, kommentiert mit [DisplaySourceCodeComments (true)]

oder es offensichtlich wieder ausschalten mit falschen

Das Attribut überprüft, ob der Kontext Ergebnis ist eine ViewResultBase, das heißt nur Views und Partials, also Json oder Content oder Redirects sind nicht betroffen, was auch sehr praktisch ist.

Schließlich mache ich diese Aktion Filter ein globalen, wenn im Debug-Modus ausgeführt wird, so dass jede Ansicht und teilweise hat die Quelle Kommentar enthalten, durch die folgende Zeile hinzufügen Global.asax.cs:

[#] DEBUG wenn

 // When in debug mode include HTML comments showing where a view or partial has come from 
     GlobalFilters.Filters.Add(new DisplaySourceCodeCommentsAttribute(true)); 

[#] endif

ich bin wirklich froh, dass ich endlich habe es sortiert, so hoffe ich, das für jemand anderen nützlich ist.