2015-10-03 10 views
5

Sto scrivendo un'implementazione personalizzata per IUserStore. La firma del metodo è creare:IUserStore <TUser> .CreateAsync: come indicare un errore nell'implementazione personalizzata?

public async virtual Task CreateAsync(TUser user) 

E che senso considerare l'interfaccia IUserStore core Microsoft.AspNet.Identity è (che è lo stesso).

Tuttavia l'interfaccia della classe UserManager definito in Microsoft.AspNet.Identity è:

public virtual Task<IdentityResult> CreateAsync(TUser user); 

Il mio problema è che non vedo come avrei dovuto passare questo IdentityResult al UserManager in quanto il tipo di ritorno in store è semplicemente "Task". Ho una logica personalizzata per determinare se un utente può o non può essere creato, quindi ho davvero bisogno di dire il risultato di CreateAsync all'UtilityManager.

Qualche idea?

+0

Nel flusso dell'applicazione, quando un utente non può essere creato, si tratta di un caso eccezionale o parte del normale flusso di esecuzione? –

+0

@YuvalItzchakov Grazie per l'interesse! Fa parte del normale flusso di esecuzione. Per dare più contesto, sto facendo la mia implementazione personalizzata di ASP.Identity in un assembly diverso, questo è il motivo per cui voglio gestire questo caso direttamente in UserStore per mantenere il cliente focalizzato sulla logica di business – reddy

risposta

4

Guardando il source code for UserManager.CreateAsync (questo è per Identity 2.0) si può vedere che prima di chiamare IUserStore.CreateAsync, si effettua una chiamata a IIdentityValidator<TUser>.ValidateAsync, che è responsabile di tornare in realtà il relativo IdentityResult oggetto:

public virtual async Task<IdentityResult> CreateAsync(TUser user) 
{ 
     ThrowIfDisposed(); 
     await UpdateSecurityStampInternal(user).ConfigureAwait(false); 
     var result = await UserValidator.ValidateAsync(user).ConfigureAwait(false); 
     if (!result.Succeeded) 
     { 
      return result; 
     } 
     if (UserLockoutEnabledByDefault && SupportsUserLockout) 
     { 
      await GetUserLockoutStore().SetLockoutEnabledAsync(user, true).ConfigureAwait(false); 
     } 
     await Store.CreateAsync(user).ConfigureAwait(false); 
     return IdentityResult.Success; 
} 

Il Lo scopo principale di IUserStore.CreateAsync è di effettuare la chiamata all'origine dati sottostante che salva i dati. Sembra che tu voglia effettivamente implementare IIdentityValidator<TUser> e impostarlo sull'istanza UserManager.

+0

Ahah abbiamo postato a lo stesso tempo!Grazie per il tuo aiuto, darò un'occhiata a IUserValidator – reddy

+0

@ red2nb Ho anche sfogliato il codice sorgente su GitHub, poi ho notato che era per ASP.NET 5. Quindi ho cercato su SymbolSource. L'interfaccia è in realtà chiamata "IIdentityValidator ", ho aggiornato la mia risposta –

+0

In realtà c'è ancora un problema con questo. La convalida che sto facendo è un controllo di integrità. Facendo affidamento su UserValidator mi manca il contesto in cui questo Validator è chiamato (creazione, aggiornamento, ecc ...). Immagino che questo validatore sia principalmente lì per verificare se sono state impostate le Proprietà e questo tipo di cose. – reddy

2

La risposta è in the source code, ecco una parte della realizzazione del UserManager al momento della scrittura:

public virtual async Task<IdentityResult> CreateAsync(TUser user, 
     CancellationToken cancellationToken = default(CancellationToken)) 
    { 
     ThrowIfDisposed(); 
     await UpdateSecurityStampInternal(user, cancellationToken); 
     var result = await ValidateUserInternal(user, cancellationToken); 
     if (!result.Succeeded) 
     { 
      return result; 
     } 
     if (Options.Lockout.EnabledByDefault && SupportsUserLockout) 
     { 
      await GetUserLockoutStore().SetLockoutEnabledAsync(user, true, cancellationToken); 
     } 
     await UpdateNormalizedUserNameAsync(user, cancellationToken); 
     await Store.CreateAsync(user, cancellationToken); 
     return IdentityResult.Success; 
    } 

Quindi, in pratica ritornano sempre vero. Ciò significa che nella versione corrente, l'inserimento dei controlli di creazione in UserStore va contro l'utilizzo previsto del framework.

Tuttavia ho notato che questo verrà modificato nella prossima versione. L'interfaccia IUserStore diventerà:

Task<IdentityResult> CreateAsync(TUser user, CancellationToken cancellationToken); 

e l'implementazione UserManager:

public virtual async Task<IdentityResult> CreateAsync(TUser user) 
    { 
     ThrowIfDisposed(); 
     await UpdateSecurityStampInternal(user); 
     var result = await ValidateUserInternal(user); 
     if (!result.Succeeded) 
     { 
      return result; 
     } 
     if (Options.Lockout.AllowedForNewUsers && SupportsUserLockout) 
     { 
      await GetUserLockoutStore().SetLockoutEnabledAsync(user, true, CancellationToken); 
     } 
     await UpdateNormalizedUserNameAsync(user); 
     await UpdateNormalizedEmailAsync(user); 

     return await Store.CreateAsync(user, CancellationToken); 
    } 

Quindi mettere la logica di creazione nella UserStore sarà possibile in quel momento. Questo sarà un modo migliore di progettare, secondo me, dal momento che il cliente non dovrebbe gestire i problemi di integrità.

+1

* Quindi in pratica restituiscono sempre true . * Se si guarda di nuovo il codice, si vedrà che se la chiamata a 'ValidateAsync' restituisce qualcosa di diverso dal successo, sarà restituito' IdentityResult' che conterrà gli errori. Quindi in realtà non sta sempre tornando vero. –

+0

Potete per favore aiutarmi con questa domanda: http: //stackoverflow.com/questions/39275597/how-to-give-custom-implementation-of-updateasync-method-of-asp-net-identity –