2013-04-19 8 views
5

Wir arbeiten an einer Art von Cloud-CMS mit ASP.NET MVC-Technologie und haben einige Hindernisse auf dem Weg gefunden. Es gibt eine Reihe von Parametern, die der Benutzer über das Bedienfeld ändern kann, um in Views zu gelangen. Beispiel: Facebook-Anwendungs-ID zum Initialisieren der Facebook JS-API. Oder zusätzlicher Text, der auf der Seite angezeigt werden soll. Oder Hintergrundbild. Momentan verwenden wir keine DI, um diese Parameter zu übertragen, stattdessen fügen wir sie dem ViewModel hinzu, aber dies ruiniert die ASP.NET MVC-Art der Arbeit mit Modellen (z. B. Formularvalidierung, Bindungen usw.)Sollte ich Dienste in meine MVC-Ansichten injizieren?

Es sieht so aus, dass die Verwendung von DI, um Dienste für die Bereitstellung von Parametern, Texten und Bildern zu injizieren, meine Ansichten weniger abhängig von Controller-spezifischen machen könnte, und es gibt sogar einige Microsoft-Technik, um es zu tun http://www.asp.net/mvc/tutorials/hands-on-labs/aspnet-mvc-4-dependency-injection#Exercise2. Es gibt jedoch viele Antworten auf Foren, die verhindern, dass Dienste mit DI in Views eingefügt werden.

Also die Frage: Was ist ein richtiger Weg, um einige Dienste in Views zu injizieren? Oder sollte ich es überhaupt nicht tun und etwas ist falsch im Anwendungsdesign?

UPDATE: einige echte Code-Beispiele (jetzt sind wir Modell unter Verwendung der Dienste zu injizieren) aus der Datenbank

Injizieren Texte (sie haben Benutzer editierbar sein, wie es CMS ist):

<div class="steps">@Html.Raw(Model.Texts["Main", "Step2"]</div> 

Injizieren von Übersetzungen aus der Datenbank (tatsächlich ist es Lokalisation):

<div class="gonfalon">@Model.Translations["Title_Winners"]</div> 

Injizieren Parameter (aus der Datenbank, COU ld ist anforderungsspezifisch; wenn die Site verschiedene Domänen zum Beispiel hat, sollte Facebook-Anwendung pro-Domain sein):

Facebook.Initialize(Model.Parameters["FbApplicationId"], Model.Parameters["FbApplicationSecret"]); 

Das Problem des aktuellen Ansatzes ist, dass dieser Code vom Wettbewerb Mechaniker genommen hat. Es ist definitiv außerhalb des Wettbewerbs Geschäftsumfang mit benutzerdefinierten Texten, Übersetzungen oder Facebook-Anwendung Id befassen. Haben die Schnipsel aus der Antwort unten geändert werden ein: Auch sie das Modell als Modell Modelle nicht unbedingt der Business-Bereich, sondern beschäftigt sich mit eine Menge Dinge tatsächlich gehört anzeigen (wie Übersetzungen und individuelle Texte)

UPDATE 2 Ruinen etwas mehr generic:

public static class WebViewPageExtensions 
{ 
    public static I ResolveService<I>(this WebViewPage page) 
    { 
     return DependencyResolver.Current.GetService<I>(); 
    } 
} 

Antwort

6

Nein, Sie sollten keine Dienste in Ansichten einfügen, aber ...

Für Szenarien wie Themes, bei denen Sie dem Thema Entwickler mehr Power geben möchten, ist nur ein Modell nicht genug. Wenn Ihr Modell beispielsweise den aktuellen Post enthält, wie kann ein Design-Designer nach einer Liste von Kategorien für die Sidebar fragen? Oder für ein Widget?

In asp.net mvc können Sie Erweiterungsmethoden verwenden, um diese Funktionalität anzubieten. Die Erweiterungsmethode verwendet den Dependency Resolver, um den Dienst zu erhalten. Auf diese Weise können Sie die erforderliche Funktionalität in der Ansicht haben, ohne einen Service tatsächlich zu injizieren.

Beachten Sie, dass das Aufrufen der Business-Schicht, um das Modell zu aktualisieren, immer noch eine Verletzung der Separation of Concerns darstellt. Die Dienste, die der Ansicht zur Verfügung gestellt werden, sollten nur Lesemodell oder allgemeine Dienstprogrammfunktionen enthalten.

Ein Beispiel

public static IMyViewServices MyServices(this WebViewPage view) 
    { 
     return DependencyResolver.Current.GetService<IMyViewServices>(); 
    } 

IMyViewServices Lebensdauer im Container sollten per http DI konfiguriert (scope) Anfrage

+0

Sieht nach der besten Lösung aus. Ich habe auch einige echte Codebeispiele für die Dinge hinzugefügt, die wir jetzt aus dem Modell nehmen, aber gerne loswerden würden. –

2

Das hängt davon ab, wie viel oder wenig Sie Ihre Controller tun wollen und in welchem ​​Grad der Trennung Sie erreichen wollen.

In meiner Welt macht der "Controller" in einer MVC-App so wenig wie möglich, weil ich eine Service-Schicht mit der gesamten Geschäftslogik und eine darüber liegende Datenschicht für die gesamte Datenbank-Interaktion habe.

Bei einem GET ruft der Controller einfach eine Servicemethode auf, die das Ansichtsmodell erstellt und es an den Controller zurückgibt, und der Controller gibt es an die Ansicht weiter. Beim POST sendet die Ansicht Daten an den Controller, der sie zur Validierung an die Serviceschicht sendet und in der DB speichert. Der Service wird in den Konstruktor des Controllers eingespeist.

Ich wäre mehr als glücklich, Code-Beispiele zu veröffentlichen, wenn Sie sie sehen möchten.

+0

Ich habe einige echte Codebeispiele für die Dinge gepostet, die wir jetzt vom Modell nehmen, aber gerne loswerden würden. Ich denke, Ihr Ansatz ist richtig; es umfasst jedoch nur den Controller, aber in unserem Fall müssen wir einige Informationen direkt aus den Ansichten (die eigentlich CMS-Vorlagen sind) sammeln. –

3

Nein, Ende der Geschichte. Warum? Hier ist warum:

Ihre Ansicht muss nur wissen, was das Ansichtsmodell, mit dem es arbeiten wird, um dieses Modell zu präsentieren. Dafür gibt es mehrere Gründe, aber die größte ist die Trennung von Bedenken. Halte deinen Blick so dumm wie möglich. Sie werden sehen, dass diese Trennung Ihnen auf dem gesamten Weg eine saubere Anwendungsstruktur geben wird.

Es gibt eine Reihe von Parametern Benutzer über das Bedienfeld ändern könnten, die wir in Ansichten, um am Ende müssen.

Ich bin mir nicht sicher, was Sie genau hier meinen, aber deshalb gibt es Ansichtmodelle. Ihre Business-Schicht wird Modelle modellieren, Ihr Controller wird sie einfach Ihren Ansichtsmodellen zuordnen und sie in die Ansicht (Präsentationsebene) weiterleiten.

+0

Ich würde definitiv mit Ihnen übereinstimmen, es ist nur eine gewöhnliche Web-Anwendung, nicht die CMS-Vorlage. Das Problem dieses Ansatzes (den wir gerade verwenden) ist, dass z.B. Für den Fotowettbewerb ist es definitiv außerhalb des Geschäftsumfangs, sich mit benutzerdefinierten Texten, Übersetzungen oder Facebook-Anwendungs-ID zu beschäftigen. Außerdem ruiniert das Model als Modellmodelle nicht eigentliche Geschäftsdomäne sondern beschäftigt sich mit vielen Dingen die eigentlich zur Ansicht gehören (wie Übersetzungen und benutzerdefinierte Texte) –

Verwandte Themen