ASP.NET 核心 MVC Encrypt/Decrypt QueryString 值
ASP.NET Core MVC Encrypt/Decrypt QueryString Values
我正在使用 ASP.NET Core 2.0 MVC、C#、Entity Framework Core Code First 和 SQL Server 2016。
我创建了一个 Web 表单,我的所有 CRUD 操作都运行良好。但是,我需要一些关于加密/解密传递给确认、编辑和删除视图的查询字符串值的帮助。
在我的索引页面上,当用户将鼠标悬停在指向这些操作方法的编辑和删除链接上时,我还想加密 EmployeeID。我不希望它们出现在索引页上。
请查看我下面的代码。
型号
public class Employee
{
public int EmployeeID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int DepartmentID { get; set; }
public Department Department { get; set; }
public int AppointmentID { get; set; }
public Appointment Appointment { get; set; }
}
public class Department
{
public int DepartmentID { get; set; }
public string Name { get; set; }
public ICollection<Employee> Employees { get; set; }
}
public class Appointment
{
public int AppointmentID { get; set; }
public string TimeSlot { get; set; }
public ICollection<Employee> Employees { get; set; }
}
DbContext
public class WinTenDbContext : DbContext
{
public WinTenDbContext(DbContextOptions<WinTenDbContext> options) : base(options)
{ }
public DbSet<Employee> Employees { get; set; }
public DbSet<Department> Departments { get; set; }
public DbSet<Appointment> Appointments { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Employee>()
.HasKey(e => e.EmployeeID);
modelBuilder.Entity<Employee>()
.Property(e => e.FirstName)
.HasColumnType("varchar(50)")
.HasMaxLength(50)
.IsRequired();
modelBuilder.Entity<Employee>()
.Property(e => e.LastName)
.HasColumnType("varchar(50)")
.HasMaxLength(50)
.IsRequired();
modelBuilder.Entity<Department>()
.HasKey(d => d.DepartmentID);
modelBuilder.Entity<Department>()
.Property(d => d.Name)
.HasColumnType("varchar(50)")
.HasMaxLength(50);
modelBuilder.Entity<Appointment>()
.HasKey(a => a.AppointmentID);
modelBuilder.Entity<Appointment>()
.Property(a => a.TimeSlot)
.HasColumnType("varchar(50)")
.HasMaxLength(50);
}
}
视图模型
public class EmployeeFormVM
{
public int EmployeeID { get; set; }
[Required(ErrorMessage = "Please enter your First Name")]
[Display(Name = "First Name")]
[StringLength(50)]
public string FirstName { get; set; }
[Required(ErrorMessage = "Please enter your Last Name")]
[Display(Name = "Last Name")]
[StringLength(50)]
public string LastName { get; set; }
[Required(ErrorMessage = "Please select your Department")]
[Display(Name = "Department")]
public int DepartmentID { get; set; }
public IEnumerable<Department> Departments { get; set; }
[Required(ErrorMessage = "Please select your Appointment")]
[Display(Name = "Appointment")]
public int AppointmentID { get; set; }
public IEnumerable<Appointment> Appointments { get; set; }
}
员工控制器
public class EmployeesController : Controller
{
private readonly WinTenDbContext _context;
public EmployeesController(WinTenDbContext context)
{
_context = context;
}
//// GET: Employees
//public async Task<IActionResult> Index()
//{
// var winTenDbContext = _context.Employees.Include(e => e.Appointment).Include(e => e.Department);
// return View(await winTenDbContext.ToListAsync());
//}
public async Task<IActionResult> Index(string sortOrder, string currentFilter, string searchString, int? page)
{
ViewData["CurrentSort"] = sortOrder;
ViewData["FirstNameSortParm"] = sortOrder == "fname" ? "fname_desc" : "fname";
ViewData["LastNameSortParm"] = String.IsNullOrEmpty(sortOrder) ? "lname_desc" : "";
ViewData["DeptNameSortParm"] = sortOrder == "deptname" ? "deptname_desc" : "deptname";
ViewData["DateSortParm"] = sortOrder == "time_slot" ? "time_slot_desc" : "time_slot";
if (searchString != null)
{
page = 1;
}
else
{
searchString = currentFilter;
}
ViewData["CurrentFilter"] = searchString;
var employees = from s in _context.Employees.Include(e => e.Appointment).Include(e => e.Department)
select s;
if (!String.IsNullOrEmpty(searchString))
{
employees = employees.Where(s => s.LastName.Contains(searchString)
|| s.FirstName.Contains(searchString));
}
switch (sortOrder)
{
case "fname":
employees = employees.OrderBy(s => s.FirstName);
break;
case "fname_desc":
employees = employees.OrderByDescending(s => s.FirstName);
break;
case "lname_desc":
employees = employees.OrderByDescending(s => s.LastName);
break;
case "deptname":
employees = employees.OrderBy(s => s.Department.Name);
break;
case "deptname_desc":
employees = employees.OrderByDescending(s => s.Department.Name);
break;
case "time_slot":
employees = employees.OrderBy(s => s.Appointment.AppointmentID);
break;
case "time_slot_desc":
employees = employees.OrderByDescending(s => s.Appointment.AppointmentID);
break;
default:
employees = employees.OrderBy(s => s.LastName);
break;
}
int pageSize = 10;
return View(await PaginatedList<Employee>.CreateAsync(employees.AsNoTracking(), page ?? 1, pageSize));
}
// GET: Employees/Details/5
public async Task<IActionResult> Details(int? id)
{
if (id == null)
{
return NotFound();
}
var employee = await _context.Employees
.Include(e => e.Appointment)
.Include(e => e.Department)
.SingleOrDefaultAsync(m => m.EmployeeID == id);
if (employee == null)
{
return NotFound();
}
return View(employee);
}
// GET: Employees/Confirmation/5
public async Task<IActionResult> Confirmation(int? id)
{
if (id == null)
{
return NotFound();
}
var employee = await _context.Employees.Include(d => d.Department).Include(a => a.Appointment)
.SingleOrDefaultAsync(m => m.EmployeeID == id);
if (employee == null)
{
return NotFound();
}
return View(employee);
}
// GET: Employees/Create
public IActionResult Create()
{
var departments = _context.Departments.ToList();
var appointments = _context.Appointments.Include(x => x.Employees).Where(x => !x.Employees.Any()).ToList();
var viewModel = new EmployeeFormVM
{
Departments = departments,
Appointments = appointments
};
return View(viewModel);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(EmployeeFormVM employee)
{
if (ModelState.IsValid)
{
var emp = new Employee();
{
emp.FirstName = employee.FirstName;
emp.LastName = employee.LastName;
emp.DepartmentID = employee.DepartmentID;
emp.AppointmentID = employee.AppointmentID;
}
// Query DB to check if Employee exists with same First/Last Name
Employee existingEmployee = await _context.Employees.SingleOrDefaultAsync(m => m.FirstName == employee.FirstName && m.LastName == employee.LastName);
if (existingEmployee != null)
{
// Display Error if duplicate employee
ModelState.AddModelError(string.Empty, "An employee with this name has already registered. Please contact the Service Desk for any scheduling conflicts.");
employee.Departments = _context.Departments.ToList();
//employee.Appointments = _context.Appointments.ToList();
employee.Appointments = _context.Appointments.ToList();
return View(employee);
}
// Query DB to check if appointment has already been assigned to an employee
Employee existingAppointment = await _context.Employees.SingleOrDefaultAsync(m => m.AppointmentID == employee.AppointmentID);
if (existingAppointment != null)
{
// Display error if the appointment was already chosen
ModelState.AddModelError(string.Empty, "This appointment has already been taken. Please select another timeslot.");
employee.Departments = _context.Departments.ToList();
//employee.Appointments = _context.Appointments.ToList();
employee.Appointments = _context.Appointments.ToList();
return View(employee);
}
_context.Add(emp);
await _context.SaveChangesAsync();
//return RedirectToAction(nameof(Index));
var newlyCreatedId = emp.EmployeeID;
return RedirectToAction(nameof(Confirmation), new { id = newlyCreatedId });
}
return View(employee);
}
// GET: Employees/Edit/5
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var employeevm = new EmployeeFormVM();
{
Employee employee = await _context.Employees.SingleOrDefaultAsync(m => m.EmployeeID == id);
if (employee == null)
{
return NotFound();
}
employeevm.EmployeeID = employee.EmployeeID;
employeevm.FirstName = employee.FirstName;
employeevm.LastName = employee.LastName;
// Retrieve list of Departments
var departments = _context.Departments.ToList();
employeevm.Departments = departments;
// Set the selected department
employeevm.DepartmentID = employee.DepartmentID;
// Retrieve list of Appointments
var appointments = _context.Appointments.ToList();
employeevm.Appointments = appointments;
// Set the selected department
employeevm.AppointmentID = employee.AppointmentID;
}
return View(employeevm);
}
// POST: Employees/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(EmployeeFormVM vmEdit)
{
if (ModelState.IsValid)
{
Employee employee = _context.Employees.SingleOrDefault(e => e.EmployeeID == vmEdit.EmployeeID);
if (employee == null)
{
return NotFound();
}
employee.FirstName = vmEdit.FirstName;
employee.LastName = vmEdit.LastName;
employee.DepartmentID = vmEdit.DepartmentID;
employee.AppointmentID = vmEdit.AppointmentID;
try
{
_context.Update(employee);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!EmployeeExists(vmEdit.EmployeeID))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
return View(vmEdit);
}
// GET: Employees/Delete/5
public async Task<IActionResult> Delete(int? id)
{
if (id == null)
{
return NotFound();
}
var employee = await _context.Employees
.Include(e => e.Appointment)
.Include(e => e.Department)
.SingleOrDefaultAsync(m => m.EmployeeID == id);
if (employee == null)
{
return NotFound();
}
return View(employee);
}
// POST: Employees/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{
var employee = await _context.Employees.SingleOrDefaultAsync(m => m.EmployeeID == id);
_context.Employees.Remove(employee);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
private bool EmployeeExists(int id)
{
return _context.Employees.Any(e => e.EmployeeID == id);
}
}
创建视图
@using (Html.BeginForm("Create", "Employees"))
{
@Html.ValidationSummary(true, "", new { @class = "validation-summary-errors" })
<div class="form-group">
@Html.LabelFor(e => e.FirstName)
@Html.TextBoxFor(e => e.FirstName, new { @class = "form-control" })
@Html.ValidationMessageFor(e => e.FirstName)
</div>
<div class="form-group">
@Html.LabelFor(e => e.LastName)
@Html.TextBoxFor(e => e.LastName, new { @class = "form-control" })
@Html.ValidationMessageFor(e => e.LastName)
</div>
<div class="form-group">
@Html.LabelFor(d => d.DepartmentID)
@Html.DropDownListFor(d => d.DepartmentID, new SelectList(Model.Departments, "DepartmentID", "Name"), "", new { @class = "form-control" })
@Html.ValidationMessageFor(d => d.DepartmentID)
</div>
<div class="form-group">
@Html.LabelFor(a => a.AppointmentID)
@Html.DropDownListFor(a => a.AppointmentID, new SelectList(Model.Appointments, "AppointmentID", "TimeSlot"), "", new { @class = "form-control" })
@Html.ValidationMessageFor(a => a.AppointmentID)
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
}
编辑视图
@using (Html.BeginForm("Edit", "Employees"))
{
<div class="form-group">
@Html.LabelFor(e => e.FirstName)
@Html.TextBoxFor(e => e.FirstName, new { @class = "form-control" })
@Html.ValidationMessageFor(e => e.FirstName)
</div>
<div class="form-group">
@Html.LabelFor(e => e.LastName)
@Html.TextBoxFor(e => e.LastName, new { @class = "form-control" })
@Html.ValidationMessageFor(e => e.LastName)
</div>
<div class="form-group">
@Html.LabelFor(d => d.DepartmentID)
@Html.DropDownListFor(d => d.DepartmentID, new SelectList(Model.Departments, "DepartmentID", "Name"), "", new { @class = "form-control" })
@Html.ValidationMessageFor(d => d.DepartmentID)
</div>
<div class="form-group">
@Html.LabelFor(a => a.AppointmentID)
@Html.DropDownListFor(a => a.AppointmentID, new SelectList(Model.Appointments, "AppointmentID", "TimeSlot"), "", new { @class = "form-control" })
@Html.ValidationMessageFor(a => a.AppointmentID)
</div>
@Html.HiddenFor(e => e.EmployeeID)
<div class="form-group">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
}
确认查看
<div class="col-md-12">
<img src="~/images/confirm.png" />
<h2>Thank you @Html.DisplayFor(model => model.FirstName) @Html.DisplayFor(model => model.LastName)!</h2>
<p>Your <b>@Html.DisplayFor(model => model.Appointment.TimeSlot)</b> appointment has been booked. If you need to reschedule this appointment, please call the Service Desk at x1380.</p>
</div>
@Max 说的对。 IDataProtectionProvider
就是你要看的。
IDataProtectionProvider
可以在 windows 或 unix 上使用。
它确实不能用作客户端 javascript 库,但仍有一些方法可以利用它。
最简单的方法是在将视图的 html 发送到浏览器之前加密 ID,并将加密的 ID 包含在 html 数据属性等中,其中您的客户端 javascript 可以通过编辑或删除请求返回 post 访问它(或者如果您愿意,可以在查询字符串中使用)。
下面是如何在控制器中使用 IDataProtectionProvider
来加密和解密 id 的示例。
public class HomeController : Controller{
IDataProtector dataProtector;
public HomeController(IDataProtectionProvider provider){
dataProtector = provider.CreateProtector(GetType().FullName);
}
[HttpGet]
public IActionResult Get() {
int id = 1234;
string encryptedId = dataProtector.Protect(id.ToString());
int decryptedId = 0;
if(int.TryParse(dataProtector.Unprotect(encryptedId), out decryptedId) == false){
throw new Exception("Invalid cypher text");
}
//at this point decryptedId contains the decrypted value.
}
请注意,当上面创建此 dataProtector 时,它使用 GetType().FullName
作为加密 "purpose"。这是出现在.net core 框架代码中的常见做法。 "purpose" 在进行加密时用作附加上下文数据,主要用于为 encrypting/decrypting 数据派生特定目的的子密钥。在这种情况下,因为我将它设置为 GetType().FullName
它将成为控制器的完全限定名称。如果您使用同一个控制器进行加密和解密,那就太好了,它可以正常工作。 BUT,如果你想在一个控制器中加密并在不同的控制器(或任何其他 class 中解密),那么重要的是要知道目的字符串在此行中传递给 dataProtector = provider.CreateProtector(purpose);
的数据保护器必须与用于解密的数据保护器相同,因为它用于加密的数据保护器。 (即,如果用于解密的 class 与用于加密的不同,则不能是 class 名称)。
此外,这篇文章可能对您有用:https://www.mikesdotnetting.com/Article/295/encryption-and-decryption-in-asp-net-core
我正在使用 ASP.NET Core 2.0 MVC、C#、Entity Framework Core Code First 和 SQL Server 2016。
我创建了一个 Web 表单,我的所有 CRUD 操作都运行良好。但是,我需要一些关于加密/解密传递给确认、编辑和删除视图的查询字符串值的帮助。
在我的索引页面上,当用户将鼠标悬停在指向这些操作方法的编辑和删除链接上时,我还想加密 EmployeeID。我不希望它们出现在索引页上。
请查看我下面的代码。
型号
public class Employee
{
public int EmployeeID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int DepartmentID { get; set; }
public Department Department { get; set; }
public int AppointmentID { get; set; }
public Appointment Appointment { get; set; }
}
public class Department
{
public int DepartmentID { get; set; }
public string Name { get; set; }
public ICollection<Employee> Employees { get; set; }
}
public class Appointment
{
public int AppointmentID { get; set; }
public string TimeSlot { get; set; }
public ICollection<Employee> Employees { get; set; }
}
DbContext
public class WinTenDbContext : DbContext
{
public WinTenDbContext(DbContextOptions<WinTenDbContext> options) : base(options)
{ }
public DbSet<Employee> Employees { get; set; }
public DbSet<Department> Departments { get; set; }
public DbSet<Appointment> Appointments { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Employee>()
.HasKey(e => e.EmployeeID);
modelBuilder.Entity<Employee>()
.Property(e => e.FirstName)
.HasColumnType("varchar(50)")
.HasMaxLength(50)
.IsRequired();
modelBuilder.Entity<Employee>()
.Property(e => e.LastName)
.HasColumnType("varchar(50)")
.HasMaxLength(50)
.IsRequired();
modelBuilder.Entity<Department>()
.HasKey(d => d.DepartmentID);
modelBuilder.Entity<Department>()
.Property(d => d.Name)
.HasColumnType("varchar(50)")
.HasMaxLength(50);
modelBuilder.Entity<Appointment>()
.HasKey(a => a.AppointmentID);
modelBuilder.Entity<Appointment>()
.Property(a => a.TimeSlot)
.HasColumnType("varchar(50)")
.HasMaxLength(50);
}
}
视图模型
public class EmployeeFormVM
{
public int EmployeeID { get; set; }
[Required(ErrorMessage = "Please enter your First Name")]
[Display(Name = "First Name")]
[StringLength(50)]
public string FirstName { get; set; }
[Required(ErrorMessage = "Please enter your Last Name")]
[Display(Name = "Last Name")]
[StringLength(50)]
public string LastName { get; set; }
[Required(ErrorMessage = "Please select your Department")]
[Display(Name = "Department")]
public int DepartmentID { get; set; }
public IEnumerable<Department> Departments { get; set; }
[Required(ErrorMessage = "Please select your Appointment")]
[Display(Name = "Appointment")]
public int AppointmentID { get; set; }
public IEnumerable<Appointment> Appointments { get; set; }
}
员工控制器
public class EmployeesController : Controller
{
private readonly WinTenDbContext _context;
public EmployeesController(WinTenDbContext context)
{
_context = context;
}
//// GET: Employees
//public async Task<IActionResult> Index()
//{
// var winTenDbContext = _context.Employees.Include(e => e.Appointment).Include(e => e.Department);
// return View(await winTenDbContext.ToListAsync());
//}
public async Task<IActionResult> Index(string sortOrder, string currentFilter, string searchString, int? page)
{
ViewData["CurrentSort"] = sortOrder;
ViewData["FirstNameSortParm"] = sortOrder == "fname" ? "fname_desc" : "fname";
ViewData["LastNameSortParm"] = String.IsNullOrEmpty(sortOrder) ? "lname_desc" : "";
ViewData["DeptNameSortParm"] = sortOrder == "deptname" ? "deptname_desc" : "deptname";
ViewData["DateSortParm"] = sortOrder == "time_slot" ? "time_slot_desc" : "time_slot";
if (searchString != null)
{
page = 1;
}
else
{
searchString = currentFilter;
}
ViewData["CurrentFilter"] = searchString;
var employees = from s in _context.Employees.Include(e => e.Appointment).Include(e => e.Department)
select s;
if (!String.IsNullOrEmpty(searchString))
{
employees = employees.Where(s => s.LastName.Contains(searchString)
|| s.FirstName.Contains(searchString));
}
switch (sortOrder)
{
case "fname":
employees = employees.OrderBy(s => s.FirstName);
break;
case "fname_desc":
employees = employees.OrderByDescending(s => s.FirstName);
break;
case "lname_desc":
employees = employees.OrderByDescending(s => s.LastName);
break;
case "deptname":
employees = employees.OrderBy(s => s.Department.Name);
break;
case "deptname_desc":
employees = employees.OrderByDescending(s => s.Department.Name);
break;
case "time_slot":
employees = employees.OrderBy(s => s.Appointment.AppointmentID);
break;
case "time_slot_desc":
employees = employees.OrderByDescending(s => s.Appointment.AppointmentID);
break;
default:
employees = employees.OrderBy(s => s.LastName);
break;
}
int pageSize = 10;
return View(await PaginatedList<Employee>.CreateAsync(employees.AsNoTracking(), page ?? 1, pageSize));
}
// GET: Employees/Details/5
public async Task<IActionResult> Details(int? id)
{
if (id == null)
{
return NotFound();
}
var employee = await _context.Employees
.Include(e => e.Appointment)
.Include(e => e.Department)
.SingleOrDefaultAsync(m => m.EmployeeID == id);
if (employee == null)
{
return NotFound();
}
return View(employee);
}
// GET: Employees/Confirmation/5
public async Task<IActionResult> Confirmation(int? id)
{
if (id == null)
{
return NotFound();
}
var employee = await _context.Employees.Include(d => d.Department).Include(a => a.Appointment)
.SingleOrDefaultAsync(m => m.EmployeeID == id);
if (employee == null)
{
return NotFound();
}
return View(employee);
}
// GET: Employees/Create
public IActionResult Create()
{
var departments = _context.Departments.ToList();
var appointments = _context.Appointments.Include(x => x.Employees).Where(x => !x.Employees.Any()).ToList();
var viewModel = new EmployeeFormVM
{
Departments = departments,
Appointments = appointments
};
return View(viewModel);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(EmployeeFormVM employee)
{
if (ModelState.IsValid)
{
var emp = new Employee();
{
emp.FirstName = employee.FirstName;
emp.LastName = employee.LastName;
emp.DepartmentID = employee.DepartmentID;
emp.AppointmentID = employee.AppointmentID;
}
// Query DB to check if Employee exists with same First/Last Name
Employee existingEmployee = await _context.Employees.SingleOrDefaultAsync(m => m.FirstName == employee.FirstName && m.LastName == employee.LastName);
if (existingEmployee != null)
{
// Display Error if duplicate employee
ModelState.AddModelError(string.Empty, "An employee with this name has already registered. Please contact the Service Desk for any scheduling conflicts.");
employee.Departments = _context.Departments.ToList();
//employee.Appointments = _context.Appointments.ToList();
employee.Appointments = _context.Appointments.ToList();
return View(employee);
}
// Query DB to check if appointment has already been assigned to an employee
Employee existingAppointment = await _context.Employees.SingleOrDefaultAsync(m => m.AppointmentID == employee.AppointmentID);
if (existingAppointment != null)
{
// Display error if the appointment was already chosen
ModelState.AddModelError(string.Empty, "This appointment has already been taken. Please select another timeslot.");
employee.Departments = _context.Departments.ToList();
//employee.Appointments = _context.Appointments.ToList();
employee.Appointments = _context.Appointments.ToList();
return View(employee);
}
_context.Add(emp);
await _context.SaveChangesAsync();
//return RedirectToAction(nameof(Index));
var newlyCreatedId = emp.EmployeeID;
return RedirectToAction(nameof(Confirmation), new { id = newlyCreatedId });
}
return View(employee);
}
// GET: Employees/Edit/5
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var employeevm = new EmployeeFormVM();
{
Employee employee = await _context.Employees.SingleOrDefaultAsync(m => m.EmployeeID == id);
if (employee == null)
{
return NotFound();
}
employeevm.EmployeeID = employee.EmployeeID;
employeevm.FirstName = employee.FirstName;
employeevm.LastName = employee.LastName;
// Retrieve list of Departments
var departments = _context.Departments.ToList();
employeevm.Departments = departments;
// Set the selected department
employeevm.DepartmentID = employee.DepartmentID;
// Retrieve list of Appointments
var appointments = _context.Appointments.ToList();
employeevm.Appointments = appointments;
// Set the selected department
employeevm.AppointmentID = employee.AppointmentID;
}
return View(employeevm);
}
// POST: Employees/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(EmployeeFormVM vmEdit)
{
if (ModelState.IsValid)
{
Employee employee = _context.Employees.SingleOrDefault(e => e.EmployeeID == vmEdit.EmployeeID);
if (employee == null)
{
return NotFound();
}
employee.FirstName = vmEdit.FirstName;
employee.LastName = vmEdit.LastName;
employee.DepartmentID = vmEdit.DepartmentID;
employee.AppointmentID = vmEdit.AppointmentID;
try
{
_context.Update(employee);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!EmployeeExists(vmEdit.EmployeeID))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
return View(vmEdit);
}
// GET: Employees/Delete/5
public async Task<IActionResult> Delete(int? id)
{
if (id == null)
{
return NotFound();
}
var employee = await _context.Employees
.Include(e => e.Appointment)
.Include(e => e.Department)
.SingleOrDefaultAsync(m => m.EmployeeID == id);
if (employee == null)
{
return NotFound();
}
return View(employee);
}
// POST: Employees/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{
var employee = await _context.Employees.SingleOrDefaultAsync(m => m.EmployeeID == id);
_context.Employees.Remove(employee);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
private bool EmployeeExists(int id)
{
return _context.Employees.Any(e => e.EmployeeID == id);
}
}
创建视图
@using (Html.BeginForm("Create", "Employees"))
{
@Html.ValidationSummary(true, "", new { @class = "validation-summary-errors" })
<div class="form-group">
@Html.LabelFor(e => e.FirstName)
@Html.TextBoxFor(e => e.FirstName, new { @class = "form-control" })
@Html.ValidationMessageFor(e => e.FirstName)
</div>
<div class="form-group">
@Html.LabelFor(e => e.LastName)
@Html.TextBoxFor(e => e.LastName, new { @class = "form-control" })
@Html.ValidationMessageFor(e => e.LastName)
</div>
<div class="form-group">
@Html.LabelFor(d => d.DepartmentID)
@Html.DropDownListFor(d => d.DepartmentID, new SelectList(Model.Departments, "DepartmentID", "Name"), "", new { @class = "form-control" })
@Html.ValidationMessageFor(d => d.DepartmentID)
</div>
<div class="form-group">
@Html.LabelFor(a => a.AppointmentID)
@Html.DropDownListFor(a => a.AppointmentID, new SelectList(Model.Appointments, "AppointmentID", "TimeSlot"), "", new { @class = "form-control" })
@Html.ValidationMessageFor(a => a.AppointmentID)
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
}
编辑视图
@using (Html.BeginForm("Edit", "Employees"))
{
<div class="form-group">
@Html.LabelFor(e => e.FirstName)
@Html.TextBoxFor(e => e.FirstName, new { @class = "form-control" })
@Html.ValidationMessageFor(e => e.FirstName)
</div>
<div class="form-group">
@Html.LabelFor(e => e.LastName)
@Html.TextBoxFor(e => e.LastName, new { @class = "form-control" })
@Html.ValidationMessageFor(e => e.LastName)
</div>
<div class="form-group">
@Html.LabelFor(d => d.DepartmentID)
@Html.DropDownListFor(d => d.DepartmentID, new SelectList(Model.Departments, "DepartmentID", "Name"), "", new { @class = "form-control" })
@Html.ValidationMessageFor(d => d.DepartmentID)
</div>
<div class="form-group">
@Html.LabelFor(a => a.AppointmentID)
@Html.DropDownListFor(a => a.AppointmentID, new SelectList(Model.Appointments, "AppointmentID", "TimeSlot"), "", new { @class = "form-control" })
@Html.ValidationMessageFor(a => a.AppointmentID)
</div>
@Html.HiddenFor(e => e.EmployeeID)
<div class="form-group">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
}
确认查看
<div class="col-md-12">
<img src="~/images/confirm.png" />
<h2>Thank you @Html.DisplayFor(model => model.FirstName) @Html.DisplayFor(model => model.LastName)!</h2>
<p>Your <b>@Html.DisplayFor(model => model.Appointment.TimeSlot)</b> appointment has been booked. If you need to reschedule this appointment, please call the Service Desk at x1380.</p>
</div>
@Max 说的对。 IDataProtectionProvider
就是你要看的。
IDataProtectionProvider
可以在 windows 或 unix 上使用。
它确实不能用作客户端 javascript 库,但仍有一些方法可以利用它。
最简单的方法是在将视图的 html 发送到浏览器之前加密 ID,并将加密的 ID 包含在 html 数据属性等中,其中您的客户端 javascript 可以通过编辑或删除请求返回 post 访问它(或者如果您愿意,可以在查询字符串中使用)。
下面是如何在控制器中使用 IDataProtectionProvider
来加密和解密 id 的示例。
public class HomeController : Controller{
IDataProtector dataProtector;
public HomeController(IDataProtectionProvider provider){
dataProtector = provider.CreateProtector(GetType().FullName);
}
[HttpGet]
public IActionResult Get() {
int id = 1234;
string encryptedId = dataProtector.Protect(id.ToString());
int decryptedId = 0;
if(int.TryParse(dataProtector.Unprotect(encryptedId), out decryptedId) == false){
throw new Exception("Invalid cypher text");
}
//at this point decryptedId contains the decrypted value.
}
请注意,当上面创建此 dataProtector 时,它使用 GetType().FullName
作为加密 "purpose"。这是出现在.net core 框架代码中的常见做法。 "purpose" 在进行加密时用作附加上下文数据,主要用于为 encrypting/decrypting 数据派生特定目的的子密钥。在这种情况下,因为我将它设置为 GetType().FullName
它将成为控制器的完全限定名称。如果您使用同一个控制器进行加密和解密,那就太好了,它可以正常工作。 BUT,如果你想在一个控制器中加密并在不同的控制器(或任何其他 class 中解密),那么重要的是要知道目的字符串在此行中传递给 dataProtector = provider.CreateProtector(purpose);
的数据保护器必须与用于解密的数据保护器相同,因为它用于加密的数据保护器。 (即,如果用于解密的 class 与用于加密的不同,则不能是 class 名称)。
此外,这篇文章可能对您有用:https://www.mikesdotnetting.com/Article/295/encryption-and-decryption-in-asp-net-core