none
Fragen zu MVC, ASP.NET Identity und EF Code First RRS feed

  • 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

    Freitag, 4. August 2017 18:52

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!

    Icon für UWP

    Cross Platform Canvas for UWP, Android, iOS

    UWP Community Toolkit Sample App

    Alle Größenangaben in UWP müssen durch 4 teilbar sein

    • Als Antwort markiert Bodenseecoder Sonntag, 14. Januar 2018 22:26
    Sonntag, 6. August 2017 19:28

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!

    Icon für UWP

    Cross Platform Canvas for UWP, Android, iOS

    UWP Community Toolkit Sample App

    Alle Größenangaben in UWP müssen durch 4 teilbar sein

    Samstag, 5. August 2017 15:48
  • 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


    Sonntag, 6. August 2017 11:34
  • 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!

    Icon für UWP

    Cross Platform Canvas for UWP, Android, iOS

    UWP Community Toolkit Sample App

    Alle Größenangaben in UWP müssen durch 4 teilbar sein

    • Als Antwort markiert Bodenseecoder Sonntag, 14. Januar 2018 22:26
    Sonntag, 6. August 2017 19:28