比方说,我有一个具有以下属性的模型Car
(为了简单起见,我跳过了get/set(:
string Name; // user can change
string Secret; // user cannot change
DateTime CreatedAt = DateTime.Now; // even we cannot change
然后在ASP Web应用程序3.1中,脚手架生成具有以下内容的Edit.cshtml.cs
(简化(:
[BindProperty]
public Car Car { get; set; }
public Task<IActionResult> OnPost()
{
_context.Attach(LanguageExporter).State = EntityState.Modified;
_context.SaveChanges();
// redirect ...
}
因此,它允许用户使用Car的所有字段进行POST。
但实际上,我想完全忽略CreatedAt
,不允许从POST参数更改Secret
(但允许从代码更改(。[BindNever]
没有帮助,因为ASP跳过了Secret
,它保留了default(string) => null
,这是我不想要的。对于CreatedAt
,它保持default(DateTime) => 01.01.0001
。
因此,我向社区提出了一个问题,即如何自动化编辑模型的过程?
在我看来,ASP应该忽略一些POST参数,EF应该忽略更新一些属性。或者ASP应该先获取模型,然后只更改特定的属性(例如,保留CreatedAt
(。
在这种情况下,最佳实践是什么?
如果您想在编辑时忽略CreatedAt
,可以将其IsModified
属性设置为false,如下所示:
_context.Attach(Car).State = EntityState.Modified;
_context.Entry<Car>(Car).Property(x => x.CreatedAt).IsModified = false;
创建API时,应该使用ViewModel,它不是数据库实体,而是请求所需属性的表示。
例如,如果允许用户编辑用户名和电话号码,则视图模型将只包含这两个属性(即使"用户"数据库实体可能包含更多属性(。然后,您会找到要更新的数据库记录,只更改需要更改的属性,然后保存更改。
class EditViewModel
{
public int Id {get;set;}
public string Name {get;set;}
public string PhoneNumber {get;set;}
}
[BindProperty]
public EditViewModel ViewModel {get;set;}
public void OnPost()
{
var entity = _context.Single(x=>x.Id == ViewModel.Id);
entity.Name = ViewModel.Name;
entity.PhoneNumber = ViewModel.PhoneNumber;
_context.SaveChanges();
}
}