Ich verwende die Unity.MVC4 Abhängigkeitsinjektion für den Zugriff auf meine Dienste. Alles funktioniert wie es sollte, wenn ich in meinen Controller-Konstruktor einfüge, aber was ich jetzt tun möchte, ist property injection in meiner Filterklasse, damit ich von innen auf meine Datenbank zugreifen kann.
Bevor ich mit dieser Frage angefangen habe, habe ich gegoogelt und verschiedene Beispiele ausprobiert, aber ich konnte keine Lösung finden, die für mich funktioniert hat.
Bootstrapper.cs
%Vor%Anwendungsstart
%Vor%Arbeitsbeispiel
%Vor%Der folgende Code, den ich Ihnen zeigen werde, ist für das Filterattribut, das ich für meine Aktionen verwenden möchte. Ich möchte einen Parameter des Typs String-Array übergeben, damit ich überprüfen kann, ob der aktuelle Benutzer auf die Aktion zugreifen darf.
In meiner Anwendung gibt es zwei Arten von Benutzern, Kontoinhaber und Gast. Alle Aktionen sind für Kontoinhaber vollständig geöffnet, für Gäste variieren sie jedoch von Aktion zu Aktion. Zum Beispiel kann eine Aktion erfordern mindestens eine von drei Berechtigungen (lesen, schreiben und bearbeiten).
Filter:
%Vor%Wenn ich diesen Filter verwenden würde, würde er ungefähr so aussehen ..
%Vor%Dies funktioniert jedoch nicht, da der Filter zwei Parameter erwartet (IRepository und string []). Es ist natürlich auch nicht möglich, hier die Konstruktorinjektion zu verwenden.
Ich habe dann versucht, John Allers Lösung zu implementieren, die gefunden werden kann hier . Es sah vielversprechend aus, aber es gab mir diesen Fehler:
Eine Ausnahme vom Typ 'Microsoft.Practices.Unity.ResolutionFailedException' ist in aufgetreten Microsoft.Practices.Unity.dll wurde aber nicht im Benutzercode behandelt
Zusätzliche Information: Auflösung der Abhängigkeit fehlgeschlagen, type = "Fildela.ClaimsAuthorizeAccountAccess", name="(none)".
Ausnahme aufgetreten während: während der Auflösung.
Ausnahme ist: InvalidOperationException - Die Eigenschaft _accountRepository vom Typ Findela.ClaimsAuthorizeAccountAccess ist nicht einstellbar.
Zum Zeitpunkt der Ausnahme war der Container:
Auflösen von Findela.ClaimsAuthorizeAccountAccess, (keine)
Irgendwelche Vorschläge, um diesen bösen Jungen zu lösen?
Danke!
Installieren Sie zunächst das offizielle Paket Unity.Mvc
anstelle von Unity.MVC4
. Dieses Paket installiert und registriert automatisch UnityFilterAttributeFilterProvider
, das wir für die Abhängigkeitsinjektion des Attributs benötigen. Du kannst überprüfen, ob deine Unity gut konfiguriert ist, indem du App_Start
& gt; UnityMvcActivator
s Start
Methode. Sie müssen folgende zwei Zeilen sehen:
Nun könnten Sie den öffentlichen Eigenschaften des Filters das Attribut [Dependency]
hinzufügen.
Wie in den Post Passiven Attributen beschrieben, ist die DI-freundliche Lösung die Trennung von AuthorizeAttribute
in 2 Teile:
Für unsere Zwecke erben wir nur AuthorizeAttribute
, um einige seiner eingebauten Funktionen zu nutzen.
Beachten Sie, dass es bei Verwendung dieses Ansatzes nicht sinnvoll ist, die Eigenschafteninjektion für Ihre Datenbankabhängigkeiten zu verwenden. Konstruktorinjektion ist sowieso immer eine bessere Wahl.
Zuerst haben wir unser Attribut, das kein Verhalten hat, um unsere Controller und Aktionen mit zu kennzeichnen. Wir fügen ein wenig Klugheit hinzu, um die Berechtigungen in einem Array zu analysieren, so dass dies nicht bei jeder Autorisierungsprüfung durchgeführt werden muss.
%Vor%Als nächstes haben wir unseren Autorisierungsfilter, der als globaler Filter fungiert.
Wir fügen ein WhiteListMode
hinzu, das standardmäßig true ist, da dies die empfohlene Methode zur Konfiguration der Sicherheit ist (Controller und Aktionen erfordern eine Anmeldung, es sei denn, sie erhalten AllowAnonymousAttribute
). Glücklicherweise ist das Framework dafür in AuthorizeAttribute
eingebaut, also verwenden wir es einfach als Flag, ob es global überprüft wird oder nicht.
Außerdem fügen wir einen Erweiterungspunkt hinzu, über den unser benutzerdefinierter Autorisierungsdienst eingespeist werden kann. Die 2 wahrscheinlichsten Dinge zu ändern sind:
Das sind die Dinge, die wir unserem Service hinzufügen. Sie können dies bei Bedarf in 2 separate Dienste umwandeln.
%Vor%Also machen wir jetzt die erweiterte Anpassung, um Ansprüche zu unterstützen. Wir trennen das, so dass es eine Naht gibt, mit der wir eine andere Instanz injizieren können, wenn sich die Geschäftslogik in der Zukunft ändert.
%Vor%Registrieren Sie Ihren Filter global und injizieren Sie seine Abhängigkeiten in Ihren Container.
%Vor%HINWEIS: Wenn Sie möchten, dass eine der Abhängigkeiten des Filters eine kürzere Lebensdauer als Singleton hat, müssen Sie
GlobalFilterProvider
wie in diese Antwort .
Und dann in Ihrem Controller, für die Sicherheit der schwarzen Liste, müssen Sie jede Aktion (oder Controller) dekorieren, um sie zu sperren.
%Vor% Für die Sicherheit der weißen Liste müssen Sie nur die Aktionen dekorieren, auf die jeder mit AllowAnonymous
Zugriff hat, oder eine ClaimsIdentityAuthorizeAttribute
mit mehr oder weniger restriktiven Berechtigungen als die globale oder Controller-Ebene hinzufügen.
Sie können keine Abhängigkeiten als Konstruktorparameter in Aktionsfilter einfügen, da sie als Attribute in C # implementiert sind. Sie müssen sie mit DependencyResolver.Current
auflösen. Es ist eine Art Service Locator und es ist nicht cool, aber Sie haben wirklich keine Wahl. ASP.NET MVC verwendet den DI-Container nicht zum Erstellen von Aktionsfilterinstanzen.
Tags und Links asp.net-mvc action-filter dependency-injection asp.net-mvc-4 unity-container