2017-10-16 227 views
1

我有一個問題在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

回答

2

首先,這是自定義模型活頁夾的一個不好的用法。數據訪問應該在控制器中進行,因爲這是控制器的責任。其次,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

那麼,腳手架只能做這麼多。人們出錯的地方是假定腳手架是它開始和結束的地方。重點是給你一個出發點。假設您將自定義代碼並使其成爲您自己的代碼。 –