[英]How to handle static classes running in the same context scope in ASP.Net Core?
In the following example I have a controller that generates a key serial Id and encrypt some sensitive information like for example SSN. 在以下示例中,我有一个控制器,该控制器生成密钥串行ID并加密一些敏感信息,例如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.
这两个类都在相同的上下文中运行并运行SP。 I think the problem lies in there.
我认为问题就在于此。
startup.cs 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 并且Serializer静态类是
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.
SqlException:不允许新事务,因为会话中正在运行其他线程。 System.Data.SqlClient.SqlConnection.OnError(SqlException exception, bool breakConnection, Action wrapCloseInAction)
System.Data.SqlClient.SqlConnection.OnError(SqlException异常,bool breakConnection,操作wrapCloseInAction)
The error returns on this controller line await _context.SaveChangesAsync();
错误在此控制器行上返回,
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. 更新检查后,我一次只能运行这些功能之一,但不能一次运行。
The DbEncryptionHandler
and DbSerializerHandler
classes do not need to have a dependency on ApplicationDbContext
, just the data they need from it. DbEncryptionHandler
和DbSerializerHandler
类不需要依赖于ApplicationDbContext
,而只需依赖它们所需的数据即可。
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);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.