asp.net 具有复杂模型的 Core 2 自定义模型绑定器
asp.net Core 2 Custom Model Binder with complex model
我在 asp.net 核心 2 中构建 Custom-Model-Binder 时遇到问题。
我读了这个 Tutorial 但这不是我需要的。
我有一个构建示例并穿上 github
我有一个像这样的简单人 Class:
public class Person
{
public int ID { get; set; }
[Required]
public string Firstname { get; set; }
[Required]
public string Surename { get; set; }
[Required]
[DisplayFormat(DataFormatString = "{0:dd.MMM.yyyy}")]
public DateTime DateOfBirth {get;set;}
[Required]
public Country Country { get; set; }
}
public class Country
{
public int ID { get; set; }
public string Name { get; set; }
public string Code { get; set; }
}
当我添加一个新人时,我可以 select 带有 HTML select 标签的国家。但是 select 标签的值是国家 ID,我希望活页夹在数据库中查找并将正确的国家放入模型中。
控制器中的创建方法如下所示:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("ID,Firstname,Surename,DateOfBirth")] Person person, int Country)
{
ViewData["Countries"] = _context.Countries.ToList();
if (ModelState.IsValid)
{
_context.Add(person);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(person);
}
我还实现了一个 IModelBinder 来绑定数据:
public class PersonEntityBinder : IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext == null)
{
throw new ArgumentNullException(nameof(bindingContext));
}
// here goes the fun
// looking for the countryId in the bindingContext
// binding everything else except the CountryID
// search the Country by countryID and put it to the model
return Task.CompletedTask;
}
}
问题是,我怎样才能像我在活页夹的评论中写的那样做到这一点?
有人有想法或最佳实践解决方案吗?
问候克里斯
首先,这是对自定义模型活页夹的错误使用。数据访问应该发生在控制器中,因为这是控制器的责任。第二,don't use [Bind]
。喜欢认真。只是不要。太可怕了,它会杀死小猫。
像这样创建一个视图模型:
public class PersonViewModel
{
public string FirstName { get; set; }
public string Surname { get; set; }
public DateTime DateOfBirth { get; set; }
public int CountryID { get; set; }
}
那么,你有没有接受这个(不再需要[Bind]
):
public async Task<IActionResult> Create(PersonViewModel model)
然后,在您的操作中,将发布的值映射到 Person
的新实例并通过从数据库中查找来填充 Country
属性:
var person = new Person
{
FirstName = model.FirstName,
Surname = model.Surname,
DateOfBirth = model.DateOfBirth,
Country = db.Countries.Find(model.CountryID)
}
然后,照常保存 person
。
我在 asp.net 核心 2 中构建 Custom-Model-Binder 时遇到问题。 我读了这个 Tutorial 但这不是我需要的。
我有一个构建示例并穿上 github
我有一个像这样的简单人 Class:
public class Person
{
public int ID { get; set; }
[Required]
public string Firstname { get; set; }
[Required]
public string Surename { get; set; }
[Required]
[DisplayFormat(DataFormatString = "{0:dd.MMM.yyyy}")]
public DateTime DateOfBirth {get;set;}
[Required]
public Country Country { get; set; }
}
public class Country
{
public int ID { get; set; }
public string Name { get; set; }
public string Code { get; set; }
}
当我添加一个新人时,我可以 select 带有 HTML select 标签的国家。但是 select 标签的值是国家 ID,我希望活页夹在数据库中查找并将正确的国家放入模型中。
控制器中的创建方法如下所示:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("ID,Firstname,Surename,DateOfBirth")] Person person, int Country)
{
ViewData["Countries"] = _context.Countries.ToList();
if (ModelState.IsValid)
{
_context.Add(person);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(person);
}
我还实现了一个 IModelBinder 来绑定数据:
public class PersonEntityBinder : IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext == null)
{
throw new ArgumentNullException(nameof(bindingContext));
}
// here goes the fun
// looking for the countryId in the bindingContext
// binding everything else except the CountryID
// search the Country by countryID and put it to the model
return Task.CompletedTask;
}
}
问题是,我怎样才能像我在活页夹的评论中写的那样做到这一点? 有人有想法或最佳实践解决方案吗?
问候克里斯
首先,这是对自定义模型活页夹的错误使用。数据访问应该发生在控制器中,因为这是控制器的责任。第二,don't use [Bind]
。喜欢认真。只是不要。太可怕了,它会杀死小猫。
像这样创建一个视图模型:
public class PersonViewModel
{
public string FirstName { get; set; }
public string Surname { get; set; }
public DateTime DateOfBirth { get; set; }
public int CountryID { get; set; }
}
那么,你有没有接受这个(不再需要[Bind]
):
public async Task<IActionResult> Create(PersonViewModel model)
然后,在您的操作中,将发布的值映射到 Person
的新实例并通过从数据库中查找来填充 Country
属性:
var person = new Person
{
FirstName = model.FirstName,
Surname = model.Surname,
DateOfBirth = model.DateOfBirth,
Country = db.Countries.Find(model.CountryID)
}
然后,照常保存 person
。