11.886 messaggi dal 09 febbraio 2002
Contributi
manuel0081 ha scritto:

Cmq il mio problema è questo:
http://stackoverflow.com/questions/25476536/isinrole-fails-after-implementing-onmodelcreating-mvc5

Ok, dice che tutto ha funzionato bene finché non ha implementato l'OnModelCreating. Infatti, si è dimenticato di invocare base.OnModelCreating(modelBuilder); per riutilizzare tutto il mapping cablato nell'IdentityDbContext.

Il metodo IsInRole in quel caso ha smesso di funzionare forse perché manca il mapping della relazione fra ruoli e utenti.
Vedo che ha semplicemente mappato le chiavi di IdentityUserLogin, IdentityRole e IdentityUserRole, ma non le relazioni che esistono fra loro.

Io ho provato con questo semplice override nell'ApplicationDbContext e il metodo IsInRole continua a funzionare anche dopo.
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    //Invoco l'OnModelCreating dell'IdentityDBContext da cui derivo
    //Così non perdo tutto il suo mapping, che so essere corretto
    base.OnModelCreating(modelBuilder);

    //Adesso aggiungo il mapping della nuova relazione tra utenti e utenti
    modelBuilder.Entity<ApplicationUser>().HasMany(user => user.UtentiCollegati).WithMany().Map(map => {
        map.MapLeftKey("IdUtentePrincipale");
        map.MapRightKey("IdUtenteCollegato");
        map.ToTable("utenti_utenti");
    });
}

Nella classe ApplicationUser ho aggiunto la proprietà UtentiCollegati.
public virtual ICollection<ApplicationUser> UtentiCollegati { get; set; }


ciao,
Moreno
Modificato da BrightSoul il 17 febbraio 2015 22.46 -

Enjoy learning and just keep making
Se eredita da IdentityDbContext<ApplicationUser> poi ho l'errore:
Invalid object name 'dbo.Utenti'.

Ormai programmano tutti... ma la professionalità appartiene a pochi
Intanto grazie della risposta. Ho ricreato un progetto aggiungendo solo il context, l'initializer e la rinomina delle tabelle. In home ho richiamato db.Users per forzare la creazione del db.
I nomi delle tabelle non cambiano...
http://expirebox.com/download/6458b4b023fb23cb1283dcf50a1ce64d.html

Se il context ereditasse da Applicationdbcontext, funzionerebbe.
User.IsInRole rimane cmq false

Anche lasciando solo Applicationdbcontext User.IsInRole restituisce sempre false.
Modificato da manuel0081 il 18 febbraio 2015 14.28 -

Ormai programmano tutti... ma la professionalità appartiene a pochi
Ho scaricato i samples di Identity. La differenza è questa.
Se nell'initializer uso:
var userManager = HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>();
            var roleManager = HttpContext.Current.GetOwinContext().Get<ApplicationRoleManager>();

nonostante abbia creato il rolemanager, il programma si blocca su:
var role = roleManager.FindByName("SuperAdmin");

e poi non so cosa accade.
Mentre se uso
var roleStore = new RoleStore<IdentityRole>(db);
var roleManager = new RoleManager<IdentityRole>(roleStore);
var applicationRoleAdministrator = new IdentityRole("SuperAdmin");
if (!roleManager.RoleExists(applicationRoleAdministrator.Name))
{
roleManager.Create(applicationRoleAdministrator);
}

il db viene creato correttamente ma User.IsInRole è sempre false.

Ormai programmano tutti... ma la professionalità appartiene a pochi
11.886 messaggi dal 09 febbraio 2002
Contributi
Ciao Manuel,
nella soluzione ho trovato due contesti: l'ApplicationDbContext e il FMEContext che hai creato tu. Hai bisogno di un solo contesto, quindi se vuoi puoi rinominare l'ApplicationDbContext che c'era già in FMEContext. Visual Studio ti permette di rinominarlo velocmente con CTRL+R CTRL+R (due volte di seguito - il primo CTRL+R ti pone nel contesto dei comandi di Refactoring, mentre il secondo lancia il comando di Renaming). In questo modo in tutte le occorrenze dell'applicazione in cui veniva usato ApplicationDbContext vedrai apprire FMEContext.

Le tabelle venivano correttamente create in italiano grazie al tuo mapping ma, dato che l'applicazione usava un secondo contesto, venivano pure ricreate coi loro nomi originali.

Ora ho modificato la soluzione in modo che ci sia un solo contesto fatto così:
public class FMEContext : IdentityDbContext<ApplicationUser>
{
    public FMEContext()
        : base("DefaultConnection", throwIfV1Schema: false)
    {
    }

    public static FMEContext Create()
    {
        return new FMEContext();
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        //Qui reimposto i nomi delle tabelle in italiano, sovrascrivendo il mapping creato dall'IdentityDbContext da cui sto derivando.
        modelBuilder.Entity<ApplicationUser>().ToTable("Utenti");
        modelBuilder.Entity<IdentityUser>().ToTable("Utenti");
        modelBuilder.Entity<IdentityUserRole>().ToTable("UtentiRuoli");
        modelBuilder.Entity<IdentityUserLogin>().ToTable("UtentiLogins");
        modelBuilder.Entity<IdentityUserClaim>().ToTable("UtentiClaims");
        modelBuilder.Entity<IdentityRole>().ToTable("Ruoli");
    }
}


Siccome ho usato la rinomina di visual studio, ora nello startup.auth.cs mi trovo automaticamente scritto:
app.CreatePerOwinContext(FMEContext.Create);


Purtroppo ieri non ho avuto tempo di esaminare l'altra questione dell'IsInRole, ma può darsi che la causa fosse la stessa: il ruolo veniva creato nel FMEContext ma poi lo User.IsInRole veniva chiamato quando sotto c'era l'ApplicationDbContext.

ciao,
Moreno

Enjoy learning and just keep making
Intanto grazie del primo chiarimento: lo sospettavo. La questione dell'isinrole però non si risolve. Ho creato un nuovo progetto con identity (non va nonostante l'unico contesto) e lo sto confrontando con winmerge con i samples scaricati da nuget (che invece funzionano)

Ormai programmano tutti... ma la professionalità appartiene a pochi
Problema risolto!
[cut]

NON BISOGNA FARLO! Bisogna solo sovrascrivere l'ApplicationUser, altrimenti User.IsInRole non funziona.

Sai darmi una motivazione al riguardo?

grazie
Modificato da manuel0081 il 20 febbraio 2015 19.16 -

Ormai programmano tutti... ma la professionalità appartiene a pochi
11.886 messaggi dal 09 febbraio 2002
Contributi
Ciao Manuel,

manuel0081 ha scritto:

Sai darmi una motivazione al riguardo?

Può darsi che c'entri l'ereditarietà. Duqnue, Entity Framework supporta l'ereditaria tra classi e può trasporla nel modello relazionale in varie forme.

Quando usi il .ToTable() per mappare sulla stessa tabella sia ApplicationUser che IdentityUser (da cui essa deriva), Entity Framework deve trovare un modo per riuscire poi a distinguerli. A tal proposito, di sua iniziativa, crea nella tabella Utenti un ulteriore campo chiamato "Discriminator" che verrà valorizzato diversamente a seconda che il record inserito sia un ApplicationUser o ad un IdentityUser.

Quel che potrebbe succedere è che, se l'utente era stato persistito come IdentityUser, poi non salta fuori quando invece l'IsInRole internamente va ad elencare tutti gli ApplicationUser.

Vedi che succede se dici ad Entity Framework di ignorare completamente il mapping di IdentityUser (non ho mai provato a farlo).
modelBuilder.Ignore<IdentityUser>();

In questo modo il campo Discriminator dovrebbe sparire dalla tabella Utenti perché ad essa sarà stato mappato solo il tipo ApplicationUser.

ciao,
Moreno
Modificato da BrightSoul il 22 febbraio 2015 23.09 -

Enjoy learning and just keep making

Torna al forum | Feed RSS

ASPItalia.com non è responsabile per il contenuto dei messaggi presenti su questo servizio, non avendo nessun controllo sui messaggi postati nei propri forum, che rappresentano l'espressione del pensiero degli autori.