2015-09-30 3 views
7

ich tue Registrierung auf dem i für 5 Dinge bin fragt:Wie erstellt man eine Transaktion mit asp.net-Identität?

Fullname, EMAILID, Passwort, ContactNumber, Geschlecht

Jetzt EMAILID und Passwort i mit Registerverfahren am Speicherung und unter zwei angegebenen Link in :

public async Task<ActionResult> Register(RegisterViewModel model) 
    { 
     if (ModelState.IsValid) 
     { 
      var user = new ApplicationUser { UserName = model.Email, Email = model.Email }; 

      using var context = new MyEntities()) 
      { 
       using (var transaction = context.Database.BeginTransaction()) 
       { 
        try 
        { 
         var DataModel = new UserMaster(); 
         DataModel.Gender = model.Gender.ToString(); 
         DataModel.Name = string.Empty; 
         var result = await UserManager.CreateAsync(user, model.Password);//Doing entry in AspnetUser even if transaction fails 
         if (result.Succeeded) 
         { 
          await this.UserManager.AddToRoleAsync(user.Id, model.Role.ToString()); 
          this.AddUser(DataModel, context); 
          transaction.Commit(); 
          return View("DisplayEmail"); 
         } 
         AddErrors(result); 
        } 
        catch (Exception ex) 
        { 
         transaction.Rollback(); 
         return null; 
        } 

       } 
      } 
     } 

     // If we got this far, something failed, redisplay form 
     return View(model); 
    } 

public int AddUser(UserMaster _addUser, MyEntities _context) 
    { 
     _context.UserMaster.Add(_addUser);   
     _context.SaveChanges(); 
     return 0; 
    } 

Jetzt mit diesem unter 2 Zeilen:

var result = await UserManager.CreateAsync(user, model.Password);//entry is done in AspnetUsers table. 
await this.UserManager.AddToRoleAsync(user.Id, model.Role.ToString());//entry is done is Aspnetuserrole table 

Jetzt dieser Fullname, Kontakt, Geschlecht habe ich in einer anderen Tabelle, die ist UserMaster. So

wenn ich mein Anmeldeformular einreichen werde ich speichern diese Details in UserMaster und AspnetUsers, AspnetUserinrole Tabelle.

Aber bedenken Sie, wenn beim Speichern des Datensatzes in UserMaster ein Problem auftritt, dann möchte ich den Eintrag in Aspnetuser und Aspnetuserrin nicht speichern.

Ich möchte eine Transaktion erstellen, bei der ich ein Rollback ausführen würde, wenn beim Speichern eines Datensatzes in einer beliebigen Tabelle ein Problem auftritt, also kein Eintrag in AspnetUser, AspnetUserinRole nd userMaster erfolgen sollte.

Datensätze sollten nur dann erfolgreich gespeichert werden, wenn kein Problem beim Speichern des Datensatzes in diesen 3 Tabellen besteht. Andernfalls sollte die whole-Transaktion die Rolle zurückgeben.

Ich verwende Microsoft.AspNet.Identity für die Anmeldung, Registrierung, Rollenverwaltung und andere und nach diesem Tutorial:

http://www.asp.net/mvc/overview/security/create-an-aspnet-mvc-5-web-app-with-email-confirmation-and-password-reset

http://www.asp.net/identity/overview/features-api/account-confirmation-and-password-recovery-with-aspnet-identity

Aber wie erwartet UserManager.CreateAsync und Usermanager .AddToRoleAsync-Methode ist in Methode integriert, wie würde ich es synchronisieren, um mit Entity-Framework zu arbeiten.

Kann mir also jemand sagen, wie man eine solche Transaktion oder irgendetwas, das das lösen würde, erstellt?

IdentityConfig:

public class ApplicationUserManager : UserManager<ApplicationUser> 
    { 
     public ApplicationUserManager(IUserStore<ApplicationUser> store) 
      : base(store) 
     { 
     } 

     public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context) 
     { 
      var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(context.Get<ApplicationDbContext>())); 
      // Configure validation logic for usernames 
      manager.UserValidator = new UserValidator<ApplicationUser>(manager) 
      { 
       AllowOnlyAlphanumericUserNames = false, 
       RequireUniqueEmail = true 
      }; 

      // Configure validation logic for passwords 
      manager.PasswordValidator = new PasswordValidator 
      { 
       RequiredLength = 6, 
       RequireNonLetterOrDigit = true, 
       RequireDigit = true, 
       RequireLowercase = true, 
       RequireUppercase = true, 
      }; 

      // Configure user lockout defaults 
      manager.UserLockoutEnabledByDefault = true; 
      manager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5); 
      manager.MaxFailedAccessAttemptsBeforeLockout = 5; 

      // Register two factor authentication providers. This application uses Phone and Emails as a step of receiving a code for verifying the user 
      // You can write your own provider and plug it in here. 
      manager.RegisterTwoFactorProvider("Phone Code", new PhoneNumberTokenProvider<ApplicationUser> 
      { 
       MessageFormat = "Your security code is {0}" 
      }); 
      manager.RegisterTwoFactorProvider("Email Code", new EmailTokenProvider<ApplicationUser> 
      { 
       Subject = "Security Code", 
       BodyFormat = "Your security code is {0}" 
      }); 
      manager.EmailService = new EmailService(); 
      manager.SmsService = new SmsService(); 
      var dataProtectionProvider = options.DataProtectionProvider; 
      if (dataProtectionProvider != null) 
      { 
       manager.UserTokenProvider = 
        new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity")); 
      } 
      return manager; 
     } 
    } 

    // Configure the application sign-in manager which is used in this application. 
    public class ApplicationSignInManager : SignInManager<ApplicationUser, string> 
    { 
     public ApplicationSignInManager(ApplicationUserManager userManager, IAuthenticationManager authenticationManager) 
      : base(userManager, authenticationManager) 
     { 
     } 

     public override Task<ClaimsIdentity> CreateUserIdentityAsync(ApplicationUser user) 
     { 
      return user.GenerateUserIdentityAsync((ApplicationUserManager)UserManager); 
     } 

     public static ApplicationSignInManager Create(IdentityFactoryOptions<ApplicationSignInManager> options, IOwinContext context) 
     { 
      return new ApplicationSignInManager(context.GetUserManager<ApplicationUserManager>(), context.Authentication); 
     } 
    } 

Antwort

6

Sie sollten keine neuen db Kontext schaffen, sondern nutzen die bestehende

var context = Request.GetOwinContext().Get<MyEntities>() 

Es pro Anfrage erstellt wird, wenn Sie Standardimplementierung verwenden

app.CreatePerOwinContext(ApplicationDbContext.Create); 

Update:

OK, da Sie verwenden zwei verschiedene Kontexte. Ihr Code wird ungefähr so ​​aussehen:

public async Task<ActionResult> Register(RegisterViewModel model) 
    { 
     if (ModelState.IsValid) 
     { 
      var user = new ApplicationUser { UserName = model.Email, Email = model.Email }; 

      var appDbContext = HttpContext.GetOwinContext().Get<ApplicationDbContext>(); 
      using(var context = new MyEntities()) 
      using (var transaction = appDbContext.Database.BeginTransaction()) 
       { 
        try 
        { 
         var DataModel = new UserMaster(); 
         DataModel.Gender = model.Gender.ToString(); 
         DataModel.Name = string.Empty; 
         var result = await UserManager.CreateAsync(user, model.Password);//Doing entry in AspnetUser even if transaction fails 
         if (result.Succeeded) 
         { 
          await this.UserManager.AddToRoleAsync(user.Id, model.Role.ToString()); 
          this.AddUser(DataModel, context); 
          transaction.Commit(); 
          return View("DisplayEmail"); 
         } 
         AddErrors(result); 
        } 
        catch (Exception ex) 
        { 
         transaction.Rollback(); 
         return null; 
        } 

       } 
     } 

     // If we got this far, something failed, redisplay form 
     return View(model); 
    } 

    public int AddUser(UserMaster _addUser, MyEntities _context) 
    { 
     _context.UserMaster.Add(_addUser); 
     _context.SaveChanges(); 
     return 0; 
    } 

hier ist appDbContext der gleiche Zusammenhang, dass

+0

Können Sie bitte Ihre ANS erweitern und versuchen, dies in meinen Code passen, weil dies das erste Mal ist, dass ich diese owin und mircosoft identity.so verwenden, ist es eine Bitte, dass Sie bitte ein wenig Details ans bereitstellen. –

+0

Es ist meine eigene mvc Vorlage, aber Code ich benutze von diesem 2 Link nur, die ich in meiner Frage –

+0

zur Verfügung gestellt habe Sehen Sie meinen aktualisierten Code und ich verwende Datenbank erste Entität Ansatz –

2

Sie können es lösen mit TransactionScope Klasse:

using (TransactionScope scope = new TransactionScope()) 
{ 
    var result = await UserManager.CreateAsync(user, model.Password); 
    if (result.Succeeded) 
    { 
     await this.UserManager.AddToRoleAsync(user.Id, model.Role.ToString()); 
     string callbackUrl = await SendEmailConfirmationTokenAsync(user.Id, "Confirm your account"); 
     return View("DisplayEmail"); 
    } 
    scope.Complete(); 
} 

So werden beide Aktionen in einer Transaktion und wenn Methode durchgeführt werden Comlete nicht, ruft beide Aktionen wird storniert (Roolback).

Wenn Sie es nur mit EF (ohne TransactionScope) lösen möchten, müssen Sie Ihren Code umgestalten. Ich weiß nicht, Implementierung der Klasse UserManager und Methoden CreateAsync und AddToRoleAsync, aber ich denke, dass sie neue DBContext für jede Operation erstellt. Zunächst einmal benötigen Sie für alle Transaktionsoperationen einen DBContext (für EF-Lösung).Wenn Sie diese Methoden hinzufügen, ändere ich meine Antwort entsprechend der EF-Lösung.

+0

von Usermanagern verwendet wird Bitte meine Frage aktualisiert mit aktualisierten Code sehen, aber nach wie vor Eintritt in AspnetUser erstellt wird, obwohl Transaktion fehlschlägt, weil CreateAsync und AddToRoleAsync nichts mit Entity Framework zu tun hat, bin ich immer noch bin mir da nicht so sicher. –

+1

@Backs 'UserManager' nimmt einen' UserStore' und 'DbContext' ist eine Konstruktorabhängigkeit in letzterem. Identity erstellt keinen Kontext für Sie - es ist bereits ein einzelner Kontext – trailmax

+0

Transaktionsbereich funktionierte bei mir nicht ... 'UserManager.CreateAsync' läuft jedes mal ab – JobaDiniz