How to handle static classes running in the same c

2019-08-19 18:29发布

In the following example I have a controller that generates a key serial Id and encrypt some sensitive information like for example SSN. I have my functions in static classes to allow me to call them from anywhere in my project. both classes are running in the same context and run SP. I think the problem lies in there.

startup.cs

    public void ConfigureServices(IServiceCollection services)
            {
                services.Configure<MvcOptions>(options =>
                {
                    options.Filters.Add(new RequireHttpsAttribute());
                });
                services.AddDbContext<ApplicationDbContext>(options =>
                    options.UseSqlServer(Configuration.GetConnectionString("ARTNetCore")));

                services.AddIdentity<ApplicationUser, IdentityRole>(config =>
                {
                    config.SignIn.RequireConfirmedEmail = true;
                })
                    .AddEntityFrameworkStores<ApplicationDbContext>()
                    .AddDefaultTokenProviders();

                // Add application services.
                services.AddTransient<IEmailSender, AuthMessageSender>();
                services.AddTransient<ISmsSender, AuthMessageSender>();
                services.Configure<SMSoptions>(Configuration);
                services.AddMvc();
                // Configure Identity
                services.Configure<IdentityOptions>(options =>
                {
                    // Password settings
                    options.Password.RequireDigit = true;
                    options.Password.RequiredLength = 8;
                    options.Password.RequireNonAlphanumeric = false;
                    options.Password.RequireUppercase = true;
                    options.Password.RequireLowercase = false;

                    // Lockout settings
                    options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(30);
                    options.Lockout.MaxFailedAccessAttempts = 10;
                    options.Lockout.AllowedForNewUsers = true;


                    services.AddCookieAuthentication(o =>
                    {
                        o.LoginPath = "/Account/LogIn";
                        o.LogoutPath = "/Account/LogOut";
                    });


                    // User settings
                    options.User.RequireUniqueEmail = true;
                });
                services.Configure<AuthMessageSenderOptions>(Configuration);

            }
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {

            var options = new RewriteOptions()
               .AddRedirectToHttps();

            app.UseRewriter(options);

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseBrowserLink();
                app.UseDatabaseErrorPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }

            app.UseStaticFiles();

            app.UseAuthentication();

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
            //Comment when migrating or demigrating

            //SeedData.Initialize(app.ApplicationServices);

        }

Controller is

private readonly ApplicationDbContext _context;

        public PatRegController(ApplicationDbContext context)
        {
            _context = context;
        }            
            [HttpPost]
            [ValidateAntiForgeryToken]
            public async Task<IActionResult> Create([Bind("FName,MName,LName,Dob,GenrId,StasId,NatyId,MarsId,CouyId,StaeId,CityId,OccnId,Email,SNN,PassNo,MobNo,LLine,MAdds,StrtNo,SDirn,AptNo,Locy,ALevl,PCode,Couy,ProeId")] PatReg patReg)
            {
                if (ModelState.IsValid)
                {
                    patReg.FileId = DbSerializerHandler.SerializeFileId(_context); 
                    patReg.SNN = DbEncryptionHandler.DynamicEncrypt(patReg.SNN, _context);
                    _context.Add(patReg);
                    await _context.SaveChangesAsync();
                    return RedirectToAction(nameof(Index));
                }
                return View(patReg);
            } 

Encryption static class is

 public static class DbEncryptionHandler
    {

        public static string DynamicEncrypt(string clearText, ApplicationDbContext _context)
        {
            try
            {
                if (!string.IsNullOrWhiteSpace(clearText))
                {

                    List<EncKeys> Keys = new List<EncKeys>();
                    Keys = _context.EncKeys.FromSql("EncKeysSP").ToList();
                    string EncryptionKey = Keys[0].DynamicKey;
                    byte[] clearBytes = Encoding.Unicode.GetBytes(clearText);
                    using (Aes encryptor = Aes.Create())
                    {
                        Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
                        encryptor.Key = pdb.GetBytes(32);
                        encryptor.IV = pdb.GetBytes(16);
                        using (MemoryStream ms = new MemoryStream())
                        {
                            using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
                            {
                                cs.Write(clearBytes, 0, clearBytes.Length);
                                cs.Close();
                            }
                            clearText = Convert.ToBase64String(ms.ToArray());
                        }
                    }
                }
                else
                {

                    clearText = null;

                }
            }
            catch (Exception ex)
            {
               throw;
            }

            return clearText;
        }
}

and Serializer static class is

 public static class DbSerializerHandler
    {
        public static Int64 SerializeFileId(ApplicationDbContext _context)
        {
            List<FileIdSeq> NewFileSeq = new List<FileIdSeq>();
            NewFileSeq = _context.FileIdSeq.FromSql("FileIdSeqSP").ToList();
            var FileID = NewFileSeq[0].LastSequence;
            return FileID;
        }
    }

When I try to save my data I get this error

An unhandled exception occurred while processing the request.

SqlException: New transaction is not allowed because there are other threads running in the session. System.Data.SqlClient.SqlConnection.OnError(SqlException exception, bool breakConnection, Action wrapCloseInAction)

The error returns on this controller line await _context.SaveChangesAsync();

What am I doing wrong here?

update I checked, I can run only one of these functions at a time but not both at the same time.

1条回答
劫难
2楼-- · 2019-08-19 19:06

The DbEncryptionHandler and DbSerializerHandler classes do not need to have a dependency on ApplicationDbContext, just the data they need from it.

public static class DbEncryptionHandler
{
   public static string DynamicEncrypt(string clearText, IEnumerable<EncKeys> keys)
   {
        ...
   }
}

public static class DbSerializerHandler
{
    public static Int64 SerializeFileId(IEnumerable<FileIdSeq> seq)
    {
        ...
    }
}

In your controller you can get the data from your context before you use your static classes.

public async Task<IActionResult> Create(PatReg patReg)
{
    if (ModelState.IsValid)
    {
        var seq = await _context.FileIdSeq.FromSql("FileIdSeqSP").ToListAsync();
        var keys = await _context.EncKeys.FromSql("EncKeysSP").ToListAsync();

        patReg.FileId = DbSerializerHandler.SerializeFileId(seq); 
        patReg.SNN = DbEncryptionHandler.DynamicEncrypt(patReg.SNN, keys);

        _context.Add(patReg);
        await _context.SaveChangesAsync();
        return RedirectToAction(nameof(Index));
    }
    return View(patReg);
} 
查看更多
登录 后发表回答