如何创建asp.net身份的交易? [英] How to create transaction with asp.net identity?

查看:223
本文介绍了如何创建asp.net身份的交易?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我做的,我要问的5件事注册:



全名,EMAILID,密码,ContactNumber,性别



现在EMAILID和密码,我正在存储与注册方法及以下两个连接给出:

 公共异步任务<&的ActionResult GT;寄存器(RegisterViewModel模型)
{
如果(ModelState.IsValid)
{
VAR用户=新ApplicationUser {用户名= model.Email,电子邮件= model.Email};

使用VAR上下文=新MyEntities())使用
{
(VAR交易= context.Database.BeginTransaction())
{
$试试b $ b {
变种的DataModel =新UserMaster();
DataModel.Gender = model.Gender.ToString();
DataModel.Name =的String.Empty;
VAR的结果=等待UserManager.CreateAsync(用户,model.Password); //否则在AspnetUser入境即使交易失败
如果(result.Succeeded)
{
等待此.UserManager.AddToRoleAsync(user.Id,model.Role.ToString());
this.AddUser(DataModel的,上下文);
器transaction.commit();
返回视图(DisplayEmail);
}
AddErrors(结果);
}
赶上(异常前)
{
transaction.Rollback();
返回NULL;
}

}
}
}

//如果我们走到这一步,事情失败了,重新显示格式为
返回视图(模型);
}

公众诠释ADDUSER(UserMaster _addUser,MyEntities _context)
{
_context.UserMaster.Add(_addUser);
_context.SaveChanges();
返回0;


$:
}

现在这个低于2线b $ b

  VAR的结果=等待UserManager.CreateAsync(用户,model.Password); //条目中AspnetUsers表完成。 
等待this.UserManager.AddToRoleAsync(user.Id,model.Role.ToString()); //项做的是Aspnetuserrole表

现在这个全名,contactno,我在另一个表是有性别的 UserMaster



因此,当我会提出我的报名表,我将保存这个细节 UserMaster和AspnetUsers,AspnetUserinrole表



但是,考虑是否有同时节省UserMaster记录,那么我不想保存Aspnetuser和Aspnetuserinrole太入门发生的任何问题。



我想创建一个事务其中,如果保存任何记录中的任何表,即没有进入应AspnetUser,AspnetUserinRole次userMaster完成过程中出现任何问题,我会回滚。



记录应保存成功只是如果在这3个表,否则whiole交易应该是角色回到节约记录没有问题的。



我使用Microsoft.AspNet.Identity为登录,注册,角色管理等,并按照本教程



http://www.asp.net/mvc/overview/security /创建-AN-ASPNET-MVC-5-web应用程序与 - 电子邮件确认和密码重置



http://www.asp.net/身份/概述/功能的API /帐户确认和密码恢复与 - ASPNET身份



但作为等待UserManager.CreateAsync和的UserManager .AddToRoleAsync方法是建立在方法如何将我synchonize它与实体框架。



所以,任何人可以指导我如何创建这样的交易或任何可能解决这个问题?



IdentityConfig

 公共类ApplicationUserManager:&的UserManager LT; ApplicationUser> 
{
公共ApplicationUserManager(IUserStore< ApplicationUser>存储)
:基(存储)
{
}

公共静态ApplicationUserManager创建( IdentityFactoryOptions< ApplicationUserManager>选项,IOwinContext上下文)
{
变种经理=新ApplicationUserManager(新UserStore< ApplicationUser>(context.Get< ApplicationDbContext>())); ApplicationUser>(经理)
{
AllowOnlyAlphanumericUserNames =假,
RequireUniqueEmail = TRUE $ B $的用户名
manager.UserValidator =新UserValidator<
//配置验证逻辑b};口令
manager.PasswordValidator =新PasswordValidator
{
RequiredLength = 6,
RequireNonLetterOrDigit = TRUE,


//配置验证逻辑RequireDigit = TRUE,
RequireLowercase = TRUE,
RequireUppercase = TRUE,
};

//配置用户锁定的默认值
manager.UserLockoutEnabledByDefault = TRUE;
manager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5);
manager.MaxFailedAccessAttemptsBeforeLockout = 5;

//注册双因素身份验证提供者。此应用程序使用手机和电子邮件作为接收码验证用户
//你可以写自己的供应商,在这里插上的步骤。
manager.RegisterTwoFactorProvider(电话区号,新PhoneNumberTokenProvider< ApplicationUser>
{
MessageFormat =您的安全码是{0}
});
manager.RegisterTwoFactorProvider(电子邮件密码,新EmailTokenProvider< ApplicationUser>
{
主题=安全码,
BodyFormat =您的安全码是{0}
});
manager.EmailService =新EmailService();
manager.SmsService =新SmsService();
VAR dataProtectionProvider = options.DataProtectionProvider;
如果(dataProtectionProvider!= NULL)
{
manager.UserTokenProvider =
新DataProtectorTokenProvider< ApplicationUser>(dataProtectionProvider.Create(ASP.NET身份));
}
返回经理;
}
}

//配置应用程序登录管理器,它是本应用中使用。
公共类ApplicationSignInManager:SignInManager< ApplicationUser,串>
{
公共ApplicationSignInManager(ApplicationUserManager的UserManager,IAuthenticationManager AuthenticationManager会)
:基地(的UserManager,AuthenticationManager会)
{
}

公众覆盖任务< ; ClaimsIdentity> CreateUserIdentityAsync(ApplicationUser用户)
{
返回user.GenerateUserIdentityAsync((ApplicationUserManager)的UserManager);
}

公共静态ApplicationSignInManager创建(IdentityFactoryOptions< ApplicationSignInManager>选项,IOwinContext上下文)
{
返回新ApplicationSignInManager(context.GetUserManager< ApplicationUserManager>(),上下文.Authentication);
}
}


解决方案

您不应该创建新的数据库环境,但使用现有的

  VAR背景= Request.GetOwinContext()获取< MyEntities>( )

如果您使用默认的实现则是每个请求创建

  app.CreatePerOwinContext(ApplicationDbContext.Create); 



更​​新:



OK,既然你使用两个不同的语境您的代码将是这个样子

 公共异步任务<&的ActionResult GT;寄存器(RegisterViewModel模型)
{
如果(ModelState.IsValid)
{
VAR用户=新ApplicationUser {用户名= model.Email,电子邮件= model.Email};

VAR appDbContext = HttpContext.GetOwinContext()获取< ApplicationDbContext>();
使用(VAR上下文=新MyEntities())使用
(VAR交易= appDbContext.Database.BeginTransaction())
{

{
VAR的DataModel =新UserMaster();
DataModel.Gender = model.Gender.ToString();
DataModel.Name =的String.Empty;
VAR的结果=等待UserManager.CreateAsync(用户,model.Password); //否则在AspnetUser入境即使交易失败
如果(result.Succeeded)
{
等待此.UserManager.AddToRoleAsync(user.Id,model.Role.ToString());
this.AddUser(DataModel的,上下文);
器transaction.commit();
返回视图(DisplayEmail);
}
AddErrors(结果);
}
赶上(异常前)
{
transaction.Rollback();
返回NULL;
}

}
}

//如果我们走到这一步,事情失败了,重新显示形式
返回查看(模型);
}

公众诠释ADDUSER(UserMaster _addUser,MyEntities _context)
{
_context.UserMaster.Add(_addUser);
_context.SaveChanges();
返回0;
}



这里appDbContext是用于通过的UserManager相同的上下文


I am doing registration on which i am asking for 5 things:

FullName,EmailId,Password,ContactNumber,Gender

Now emailid and password i am storing with register method and given in below two link:

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;
    }

Now with this below 2 lines:

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

Now this Fullname,contactno,gender i am having in another table that is UserMaster.

So when i will submit my registration form i will save this details in UserMaster and AspnetUsers,AspnetUserinrole table.

But consider if there any problem occurs while saving record in UserMaster then i dont want to save entry in Aspnetuser and Aspnetuserinrole too.

I would like to create a transaction where i would rollback if any problem occurs during saving any record in any table i.e no entry should be done in AspnetUser,AspnetUserinRole nd userMaster.

Records should be saved successfully only if there is no problem in saving record in this 3 tables otherwise whiole transaction should be role back.

I am using Microsoft.AspNet.Identity for login,Register,role management and other and following this 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

But as await UserManager.CreateAsync and UserManager.AddToRoleAsync method are built in method how would i synchonize it to work with entity framework.

So can anybody guide me how to create such transaction or anything that would solve this?

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);
        }
    }

解决方案

You should not create new db context, but use the existing one

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

It is created per request if you use default implementation

app.CreatePerOwinContext(ApplicationDbContext.Create);

Update:

OK, since you are using two different contexts your code will look something like this

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;
    }

here appDbContext is the same context that is used by UserManager

这篇关于如何创建asp.net身份的交易?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆