Benutzer mit den meisten Antworten
Fragen zu MVC, ASP.NET Identity und EF Code First

Frage
-
Guten Abend,
ich bin neu in ASP.NET und sitze gerade an meinem ersten MVC Projekt. Die Datenstruktur hinter der Anwendung soll dabei mit EF CodeFirst erstellt werden. Da ich mit EF ebenfalls keine Erfahrungen habe, sind einige Fragen aufgetaucht, zu denen ich auch nach langer Suche im Internet keine besonders brauchbaren Informationen gefunden habe.
In meiner Anwendung habe ich zwei Rollen. Dabei soll ein User der übergeordneten Rolle mehrere andere User als Abhängigkeit haben. Konkret geht es dabei um Organisationsadministratoren, die mehrere Mitarbeiter haben. Wie gehe ich in diesem Fall vor? Soll ich ein Model für die Organisationen erstellen, und dann ApplicationUser als List implementieren?
Dabei komme ich auch schon zu meiner nächsten Frage: Wenn ich Scaffolding nutze, um wie im MVC Introduction Course am Beispiel des MvcMusicStore Examples einem Artist mehrere Albums zuzuordnen, indem ich in Artist eine List (of Artist) implementiere, und in Album eine Album as Album und eine AlbumID as Integer hinzufüge, so erstellt Scaffolding automatisch ein DropDown im Album Create View. Wenn ich das gleiche mit ApplicationUser mache, so erkennt Scaffolding das nicht, und erstellt folglich auch kein Dropdown im entsprechenden View. Ist die oben genannte Vorgehensweise soweit korrekt, oder gibt es noch etwas anderes zu beachten?
Beim Erstellen der Rollen in Startup.vb tritt bei mir folgender Fehler auf:
Serverfehler in der Anwendung /. Mehrere Objektsätze pro Typ werden nicht unterstützt. Die Objektsätze 'ApplicationUsers' und 'Users' können beide Instanzen vom Typ 'StundenProtokollMVC.ApplicationUser' enthalten. Beschreibung: Unbehandelte Ausnahme beim Ausführen der aktuellen Webanforderung. Überprüfen Sie die Stapelüberwachung, um weitere Informationen über diesen Fehler anzuzeigen und festzustellen, wo der Fehler im Code verursacht wurde. Ausnahmedetails: System.InvalidOperationException: Mehrere Objektsätze pro Typ werden nicht unterstützt. Die Objektsätze 'ApplicationUsers' und 'Users' können beide Instanzen vom Typ 'StundenProtokollMVC.ApplicationUser' enthalten. Quellfehler: Zeile 18: Dim UserManager = New UserManager(Of ApplicationUser)(New UserStore(Of ApplicationUser)(context)) Zeile 19: Zeile 20: If Not roleManager.RoleExists("Admin") Then Zeile 21: Dim role = New Microsoft.AspNet.Identity.EntityFramework.IdentityRole() Zeile 22: role.Name = "Admin" Quelldatei: d:\eigene dokumente\dokumente\visual studio 2017\Projects\StundenProtokollMVC\StundenProtokollMVC\Startup.vb Zeile: 20 Stapelüberwachung: [InvalidOperationException: Mehrere Objektsätze pro Typ werden nicht unterstützt. Die Objektsätze 'ApplicationUsers' und 'Users' können beide Instanzen vom Typ 'StundenProtokollMVC.ApplicationUser' enthalten.] System.Data.Entity.Internal.DbSetDiscoveryService.RegisterSets(DbModelBuilder modelBuilder) +456 System.Data.Entity.Internal.LazyInternalContext.CreateModelBuilder() +360 System.Data.Entity.Internal.LazyInternalContext.CreateModel(LazyInternalContext internalContext) +15 System.Data.Entity.Internal.RetryLazy`2.GetValue(TInput input) +123 System.Data.Entity.Internal.LazyInternalContext.InitializeContext() +616 System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(Type entityType) +18 System.Data.Entity.Internal.Linq.InternalSet`1.Initialize() +53 System.Data.Entity.Internal.Linq.InternalSet`1.get_InternalContext() +16 System.Data.Entity.Infrastructure.DbQuery`1.System.Linq.IQueryable.get_Provider() +39 System.Data.Entity.QueryableExtensions.FirstOrDefaultAsync(IQueryable`1 source, Expression`1 predicate, CancellationToken cancellationToken) +154 System.Data.Entity.QueryableExtensions.FirstOrDefaultAsync(IQueryable`1 source, Expression`1 predicate) +163 Microsoft.AspNet.Identity.EntityFramework.RoleStore`3.FindByNameAsync(String roleName) +573 Microsoft.AspNet.Identity.<FindByNameAsync>d__13.MoveNext() +118 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +99 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +58 Microsoft.AspNet.Identity.CultureAwaiter`1.GetResult() +59 Microsoft.AspNet.Identity.<RoleExistsAsync>d__d.MoveNext() +284 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +99 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +58 Microsoft.AspNet.Identity.AsyncHelper.RunSync(Func`1 func) +174 Microsoft.AspNet.Identity.RoleManagerExtensions.RoleExists(RoleManager`2 manager, String roleName) +104 StundenProtokollMVC.Startup.createRolesandUsers() in d:\eigene dokumente\dokumente\visual studio 2017\Projects\StundenProtokollMVC\StundenProtokollMVC\Startup.vb:20 StundenProtokollMVC.Startup.Configuration(IAppBuilder app) in d:\eigene dokumente\dokumente\visual studio 2017\Projects\StundenProtokollMVC\StundenProtokollMVC\Startup.vb:11 [TargetInvocationException: Ein Aufrufziel hat einen Ausnahmefehler verursacht.] System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor) +0 System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments) +160 System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) +101 Owin.Loader.<>c__DisplayClass12.<MakeDelegate>b__b(IAppBuilder builder) +66 Owin.Loader.<>c__DisplayClass1.<LoadImplementation>b__0(IAppBuilder builder) +123 Microsoft.Owin.Host.SystemWeb.<>c__DisplayClass2.<InitializeBlueprint>b__0(IAppBuilder builder) +71 Microsoft.Owin.Host.SystemWeb.OwinAppContext.Initialize(Action`1 startup) +462 Microsoft.Owin.Host.SystemWeb.OwinBuilder.Build(Action`1 startup) +40 Microsoft.Owin.Host.SystemWeb.OwinHttpModule.InitializeBlueprint() +70 System.Threading.LazyInitializer.EnsureInitializedCore(T& target, Boolean& initialized, Object& syncLock, Func`1 valueFactory) +115 Microsoft.Owin.Host.SystemWeb.OwinHttpModule.Init(HttpApplication context) +106 System.Web.HttpApplication.RegisterEventSubscriptionsWithIIS(IntPtr appContext, HttpContext context, MethodInfo[] handlers) +536 System.Web.HttpApplication.InitSpecial(HttpApplicationState state, MethodInfo[] handlers, IntPtr appContext, HttpContext context) +173 System.Web.HttpApplicationFactory.GetSpecialApplicationInstance(IntPtr appContext, HttpContext context) +336 System.Web.Hosting.PipelineRuntime.InitializeApplication(IntPtr appContext) +296 [HttpException (0x80004005): Ein Aufrufziel hat einen Ausnahmefehler verursacht.] System.Web.HttpRuntime.FirstRequestInit(HttpContext context) +10044576 System.Web.HttpRuntime.EnsureFirstRequestInit(HttpContext context) +95 System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context) +254
Leider habe ich im Web nichts zu diesem Fehler gefunden.
Das ist leider eine ganze Menge an Unwissen :-/
Vielen Dank im Voraus,
Bodenseecoder
Antworten
-
Deinen Ansatz hört sie so gut an.
Wie ich schon oben geschrieben habe würde ich den Identity Provider beim Standard lassen. In meinen 8 Jahren ASP.Net habe ich des öfteren erleben das Microsoft etwas daran verändert hat und man immer wieder von neu anfangen musste. Auch würde ich dafür eine andere Datenbank verwenden und die erzeugte so lassen wie sie ist.
Erstelle dir außerhalb davon Rollen und passe den Regierungsprozess deinen Wünschen an. Erstelle dir eine eigene Klassen die, die Prüfung der Rollen übernimmt.
Eine Anhängigkeit zu anderen Tabellen kannst Du so wie hier beschrieben erstellen Link.
Gruß Thomas
Sage nie, ich kann es nicht - sage nur, ich kann es noch nicht!
Cross Platform Canvas for UWP, Android, iOS
- Als Antwort markiert Bodenseecoder Sonntag, 14. Januar 2018 22:26
Alle Antworten
-
Hallo Bodenseecoder,
erstmal solltest Du dir Gedanken darüber machen wie die User mit den entsprechenden Rollen angelegt werden. Legt der Admin die untergeordneten Rollen an oder legen sich die User selbst an? Wenn sich die User selbst anlegen, woher sollen sie wissen zu welcher Adminrolle sie gehören.
Ich würde die Rollen Zuweisung und Verwaltung außerhalb vom UserManager machen und den UserManager beim Standard halten.
Klassische Rollen sind z.B. Admin und User, dabei ist der Admin für alle User verantwortlich. In deinem Fall ist das etwas anders. Zuerst solltest Du eine Organisation anlegen die Organisation hat ein oder mehre Admins zudem x User. Das klassische Rollensystem passt hier nicht
Gruß Thomas
Sage nie, ich kann es nicht - sage nur, ich kann es noch nicht!
Cross Platform Canvas for UWP, Android, iOS
-
Vielen Dank für Ihre Antwort!
Also ist der Ansatz, ein Model für die Organisation zu erstellen, welches beim Registrieren einer neuen Organisation erstellt wird, und dabei direkt ein User mit der Rolle "Organisationsadministator" erstellt, so in Ordnung? Es gäbe also in ASP.NET Identity zwei Rollen, einmal Organisationsadministrator und Organisationsmitarbeiter, welche beide in der Mitglieder-Property des Organisationsmodels gehalten werden. Ist das theoretisch so in Ordnung?
Dabei ist meine nächste Frage: wir implementiere ich eine Relation mit ApplicationUser? Ist das in wie folgt korrekt, damit EF eine Relation erkennt?
Public Class Organization Private m_OrganizationID As Integer Public Property OrganizationID() As Integer Get Return m_OrganizationID End Get Set(ByVal value As Integer) m_Organization = value End Set End Property Private m_Name As String Public Property Name() As String Get Return m_Name End Get Set(ByVal value As String) m_Name = value End Set End Property Private m_ApplicationUsers As List(Of ApplicationUser) Public Property ApplicationUsers() As List(Of ApplicationUser) Get Return m_ApplicationUsers End Get Set(ByVal value As List(Of ApplicationUser)) m_ApplicationUsers = value End Set End Property End Class
Public Class ApplicationUser Inherits IdentityUser Private m_OrganizationID As String Public Property OrganizationID() As String Get Return m_OrganizationID End Get Set(ByVal value As String) m_OrganizationID = value End Set End Property Private m_Organization As Business Public Property Organization() As Business Get Return m_Organization End Get Set(ByVal value As Organization) m_Organization = value End Set End Property Public Async Function GenerateUserIdentityAsync(manager As UserManager(Of ApplicationUser)) As Task(Of ClaimsIdentity) ' Beachten Sie, dass der "authenticationType" mit dem in "CookieAuthenticationOptions.AuthenticationType" definierten Typ übereinstimmen muss. Dim userIdentity = Await manager.CreateIdentityAsync(Me, DefaultAuthenticationTypes.ApplicationCookie) ' Benutzerdefinierte Benutzeransprüche hier hinzufügen Return userIdentity End Function End Class
Vielen Dank im Voraus,
Bodenseecoder
-
Deinen Ansatz hört sie so gut an.
Wie ich schon oben geschrieben habe würde ich den Identity Provider beim Standard lassen. In meinen 8 Jahren ASP.Net habe ich des öfteren erleben das Microsoft etwas daran verändert hat und man immer wieder von neu anfangen musste. Auch würde ich dafür eine andere Datenbank verwenden und die erzeugte so lassen wie sie ist.
Erstelle dir außerhalb davon Rollen und passe den Regierungsprozess deinen Wünschen an. Erstelle dir eine eigene Klassen die, die Prüfung der Rollen übernimmt.
Eine Anhängigkeit zu anderen Tabellen kannst Du so wie hier beschrieben erstellen Link.
Gruß Thomas
Sage nie, ich kann es nicht - sage nur, ich kann es noch nicht!
Cross Platform Canvas for UWP, Android, iOS
- Als Antwort markiert Bodenseecoder Sonntag, 14. Januar 2018 22:26