Ich habe eine Website mit einer Layoutseite. Diese Layoutseite enthält jedoch Daten, für die alle Seitenmodelle den Seitentitel, den Seitennamen und den Ort angeben müssen, an dem wir uns tatsächlich für einen HTML-Helfer befinden, den ich ausgeführt habe und der eine Aktion ausführt. Außerdem hat jede Seite ihre eigenen Eigenschaften für Ansichtsmodelle.
Wie kann ich das machen? Es scheint eine schlechte Idee zu sein, ein Layout einzugeben, aber wie übergebe ich diese Informationen?
asp.net-mvc-4
Rushino
quelle
quelle
ViewBag
. Vielleicht eine Frage der Vorlieben. Upvoted Ihren KommentarAntworten:
Wenn Sie an jede Seite dieselben Eigenschaften übergeben müssen, ist es ratsam, ein Basisansichtsmodell zu erstellen, das von allen Ihren Ansichtsmodellen verwendet wird. Ihre Layoutseite kann dann dieses Basismodell übernehmen.
Wenn hinter diesen Daten Logik erforderlich ist, sollte diese in einen Basiscontroller gestellt werden, der von allen Ihren Controllern verwendet wird.
Es gibt eine Menge Dinge, die Sie tun können. Der wichtige Ansatz besteht darin, denselben Code nicht an mehreren Stellen zu wiederholen.
Bearbeiten: Update von Kommentaren unten
Hier ist ein einfaches Beispiel, um das Konzept zu demonstrieren.
Erstellen Sie ein Basisansichtsmodell, von dem alle Ansichtsmodelle erben.
Ihre Layoutseite kann dies als Modell verwenden.
Stellen Sie schließlich die Daten in der Aktionsmethode ein.
quelle
public class HomeController : BaseController
. Auf diese Weise muss der gemeinsame Code nur einmal geschrieben werden und kann auf alle Controller angewendet werden.Ich habe den RenderAction HTML-Helfer für Rasiermesser im Layout verwendet.
Ich brauchte es für eine einfache Saite. Meine Aktion gibt also einen String zurück und schreibt ihn einfach in der Ansicht auf. Wenn Sie jedoch komplexe Daten benötigen, können Sie PartialViewResult und model zurückgeben.
Sie müssen Ihr Modell nur an den Anfang der von Ihnen erstellten Teilansicht '_maPartialView.cshtml' setzen
Dann können Sie Daten im Modell in dieser Teilansicht mit HTML verwenden.
quelle
Eine weitere Option besteht darin, eine separate LayoutModel-Klasse mit allen Eigenschaften zu erstellen, die Sie im Layout benötigen, und anschließend eine Instanz dieser Klasse in ViewBag einzufügen. Ich benutze die Controller.OnActionExecuting-Methode, um sie zu füllen. Zu Beginn des Layouts können Sie dieses Objekt dann aus ViewBag zurückziehen und weiterhin auf dieses stark typisierte Objekt zugreifen.
quelle
OnActionExecuting
. Die Verwendung von ViewBag bedeutet auch, dass Sie die Typensicherheit in Ihrem Controller verlieren, was niemals gut ist.Vermutlich besteht der Hauptanwendungsfall hierfür darin, ein Basismodell für alle (oder die meisten) Controller-Aktionen in die Ansicht zu bringen.
Angesichts dessen habe ich eine Kombination aus mehreren dieser Antworten verwendet, wobei ich mich hauptsächlich auf Colin Bacons Antwort stützte.
Es ist richtig, dass dies immer noch Controller-Logik ist, da wir ein Ansichtsmodell füllen, um zu einer Ansicht zurückzukehren. Daher ist der richtige Ort, um dies zu platzieren, in der Steuerung.
Wir möchten, dass dies auf allen Controllern geschieht, da wir dies für die Layoutseite verwenden. Ich verwende es für Teilansichten, die auf der Layoutseite gerendert werden.
Wir möchten auch weiterhin den zusätzlichen Vorteil eines stark typisierten ViewModel
Daher habe ich ein BaseViewModel und einen BaseController erstellt. Alle ViewModels-Controller erben von BaseViewModel bzw. BaseController.
Der Code:
BaseController
Beachten Sie die Verwendung von OnActionExecuted aus diesem SO-Beitrag
HomeController
BaseViewModel
HomeViewModel
FooterModel
Layout.cshtml
_Nav.cshtml
Hoffentlich hilft das.
quelle
Sie müssen sich nicht mit Aktionen herumschlagen oder das Modell ändern, sondern nur einen Basis-Controller verwenden und den vorhandenen Controller aus dem Kontext der Layoutansicht umwandeln.
Erstellen Sie einen Basis-Controller mit den gewünschten gemeinsamen Daten (Titel / Seite / Speicherort usw.) und der Aktionsinitialisierung ...
Stellen Sie sicher, dass jeder Controller den Basis-Controller verwendet ...
Übertragen Sie den vorhandenen Basis-Controller aus dem Ansichtskontext auf Ihrer
_Layout.cshml
Seite ...Jetzt können Sie auf Ihrer Layoutseite auf Werte in Ihrem Basis-Controller verweisen.
AKTUALISIEREN
Sie können auch eine Seitenerweiterung erstellen, die Sie verwenden können
this
.Dann müssen Sie nur noch daran denken,
this.Controller()
den Controller zu verwenden, wenn Sie ihn möchten.oder spezifischer Controller, der von
_BaseController
... erbt .quelle
Wenn Sie ein ganzes Modell übergeben möchten, gehen Sie wie folgt in das Layout:
und fügen Sie dies in der Steuerung hinzu:
quelle
Ich denke nicht, dass eine dieser Antworten für eine große Anwendung auf Unternehmensebene flexibel genug ist. Ich bin kein Fan von übermäßigem Gebrauch des ViewBag, aber in diesem Fall würde ich aus Gründen der Flexibilität eine Ausnahme machen. Folgendes würde ich tun ...
Sie sollten einen Basis-Controller auf allen Ihren Controllern haben. Fügen Sie Ihre Layoutdaten OnActionExecuting in Ihrem Basis-Controller hinzu (oder OnActionExecuted, wenn Sie dies verschieben möchten) ...
Ziehen Sie dann in Ihrer _Layout.cshtml Ihr ViewModel aus dem ViewBag ...
Oder...
Dadurch wird die Codierung für die Controller oder Ansichtsmodelle Ihrer Seite nicht beeinträchtigt.
quelle
MyLayoutViewModel
dynamisch erstellte haben, wie kann ich einige Parameter an dieOnActionExecuting
Methode übergeben?base.OnActionExecuting(filterContext)
in deinerOnActionExecuting
Methode !!!Das Erstellen einer Basisansicht, die das Modell der Layoutansicht darstellt, ist ein schrecklicher Ansatz. Stellen Sie sich vor, Sie möchten ein Modell haben, das die im Layout definierte Navigation darstellt. Würden Sie tun
CustomersViewModel : LayoutNavigationViewModel
? Warum? Warum sollten Sie die Navigationsmodelldaten durch jedes einzelne Ansichtsmodell leiten, das Sie in der Lösung haben?Das Layout-Ansichtsmodell sollte eigenständig dediziert sein und den Rest der Ansichtsmodelle nicht dazu zwingen, davon abhängig zu sein.
Stattdessen können Sie dies in Ihrer
_Layout.cshtml
Datei tun :Am wichtigsten ist, wir müssen nicht
new LayoutViewModel()
und wir werden alle Abhängigkeiten bekommenLayoutViewModel
, die für uns gelöst wurden.z.B
quelle
Scoped
Layoutmodellobjekt in ASP..Net Core wäre.Andere Antworten haben so ziemlich alles darüber behandelt, wie wir das Modell an unsere Layoutseite übergeben können. Ich habe jedoch einen Weg gefunden, mit dem Sie Variablen dynamisch an Ihre Layoutseite übergeben können, ohne ein Modell oder eine Teilansicht in Ihrem Layout zu verwenden. Nehmen wir an, Sie haben dieses Modell -
Und Sie wollen Stadt und Staat dynamisch bekommen. Zum Beispiel
In Ihrer index.cshtml können Sie diese beiden Variablen in ViewBag einfügen
Und dann können Sie in Ihrer layout.cshtml auf diese Viewbag-Variablen zugreifen
quelle
Es gibt noch einen anderen Weg, damit umzugehen. Aus architektonischer Sicht vielleicht nicht der sauberste Weg, aber es vermeidet viel Schmerz, der mit den anderen Antworten verbunden ist. Fügen Sie einfach einen Dienst in das Razor-Layout ein und rufen Sie dann eine Methode auf, die die erforderlichen Daten abruft:
Dann später in der Layoutansicht:
Wiederum nicht sauber in Bezug auf die Architektur (offensichtlich sollte der Dienst nicht direkt in die Ansicht eingefügt werden), aber er erledigt den Job.
quelle
@inject
ist meiner Meinung nach die beste Lösung.Sie können auch RenderSection verwenden . Es hilft Ihnen, Ihre
Model
Daten in die_Layout
Ansicht einzufügen .Sie können injizieren
View Model
Daten,Json
,Script
,CSS
,HTML
usw.In diesem Beispiel spritze
Json
ich vonIndex
Ansicht zuLayout
Ansicht.Index.chtml
_Layout.cshtml
Dadurch entfällt die Notwendigkeit, eine separate Basis zu erstellen
View Model
.Hoffnung hilft jemandem.
quelle
Was ich getan habe, ist sehr einfach und es funktioniert
Deklarieren Sie die statische Eigenschaft in einem beliebigen Controller, oder Sie können eine Datenklasse mit statischen Werten erstellen, wenn Sie dies möchten:
Diese Werte können von den Controllern basierend auf Operationen aktualisiert werden. später können Sie sie in Ihrem _Layout verwenden
In _layout.cshtml
quelle
Warum hat niemand Erweiterungsmethoden für ViewData vorgeschlagen?
Option 1
Scheint mir bei weitem die am wenigsten aufdringliche und einfachste Lösung für das Problem. Keine fest codierten Zeichenfolgen. Keine auferlegten Einschränkungen. Keine magische Kodierung. Kein komplexer Code.
Stellen Sie die Daten auf der Seite ein
Option 2
Eine weitere Option, die die Felddeklaration erleichtert.
Stellen Sie die Daten auf der Seite ein. Die Deklaration ist einfacher als die erste Option, aber die Verwendungssyntax ist etwas länger.
Option 3
Dann können Sie dies mit der Rückgabe eines einzelnen Objekts kombinieren, das alle layoutbezogenen Felder mit ihren Standardwerten enthält.
Stellen Sie die Daten auf der Seite ein
Diese dritte Option hat mehrere Vorteile und ich denke, sie ist in den meisten Fällen die beste Option:
Einfachste Deklaration von Feldern und Standardwerten.
Einfachste Verwendungssyntax beim Festlegen mehrerer Felder.
Ermöglicht das Festlegen verschiedener Arten von Daten in den ViewData (z. B. Layout, Header, Navigation).
Ermöglicht zusätzlichen Code und Logik innerhalb der LayoutData-Klasse.
PS Vergessen Sie nicht, den Namespace von ViewDataExtensions in _ViewImports.cshtml hinzuzufügen
quelle
Sie können eine Rasiermesserdatei im Ordner App_Code erstellen und dann über Ihre Ansichtsseiten darauf zugreifen.
Projekt> Repository / IdentityRepository.cs
Projekt> App_Code / IdentityRepositoryViewFunctions.cshtml:
Projekt> Ansichten / Freigegeben / _Layout.cshtml (oder eine andere .cshtml-Datei)
quelle
Anstatt dies durchzugehen, können Sie immer einen anderen Ansatz verwenden, der auch schnell ist
Erstellen Sie eine neue Teilansicht im freigegebenen Verzeichnis und rufen Sie Ihre Teilansicht in Ihrem Layout als auf
In Ihrer Teilansicht können Sie Ihre Datenbank aufrufen und ausführen, was immer Sie möchten
Angenommen, Sie haben Ihre Entity Framework-Datenbank hinzugefügt
quelle
Es ist unglaublich, dass hier niemand das gesagt hat. Das Übergeben eines Ansichtsmodells durch einen Basis-Controller ist ein Chaos. Wir verwenden Benutzeransprüche , um Informationen an die Layoutseite zu übergeben (zum Beispiel zum Anzeigen von Benutzerdaten in der Navigationsleiste). Es gibt noch einen Vorteil. Die Daten werden über Cookies gespeichert, sodass die Daten in jeder Anfrage nicht über Teilabrufe abgerufen werden müssen. Googeln Sie einfach ein bisschen "asp net identity Claims".
quelle
Sie können wie folgt verwenden:
quelle