我在asp.net core 2中构建Custom-Model-Binder时遇到问题。 我读了Tutorial但这不是我需要的。
我有一个构建示例并放在github
上我有一个简单的Person类:
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; }
}
当我添加新人时,我可以选择带有HTML选择标记的国家/地区。但是select标签的值是国家标识,我希望绑定器在数据库中查找并将正确的国家/地区放入模型中。
Controller中的create方法如下所示:
[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;
}
}
问题是,我怎么能这样做,就像我在Binder的评论中写的那样? 任何想法或最佳实践解决方案?
问候克里斯
答案 0 :(得分:3)
首先,这是对自定义模型绑定器的错误使用。数据访问应该在控制器中进行,因为这是控制器的责任。第二,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
。