asp.net Core 2自定义模型绑定器与复杂模型

问题描述:

我有一个问题在asp.net核心2中构建一个自定义模型绑定器。 我读了这个Tutorial但这不是我所需要的。asp.net Core 2自定义模型绑定器与复杂模型

我有一个构建为例,换上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标签的价值是国家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; 
    } 
} 

的问题是,我怎么能做到这一点像我写的在Binder的评论中? 任何人的想法或最佳实践解决方案?

关于克里斯

+0

为什么你想做一些复杂的基本动作?只需添加属性public int CountryId {get;设置;}到你的模型,并在其上设置国家ID。实体框架将为你做其余的事情 – OrcusZ

首先,这是自定义模型活页夹的一个不好的用法。数据访问应该在控制器中进行,因为这是控制器的责任。其次,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,照常。

+0

好吧,我从一些Java框架知道的方式,在我看来这是最好的方法。看起来我不能信任Visual Studio的脚手架代码。谢谢 –

+0

那么,脚手架只能做这么多。人们出错的地方是假定脚手架是它开始和结束的地方。重点是给你一个出发点。假设您将自定义代码并使其成为您自己的代码。 –