2011-09-19 71 views
8

我一直在MVC最近工作,我很好奇初始化我的視圖模型的最佳方式是什麼。我應該直接在控制器中映射它,還是應該在視圖模型的構造函數中初始化屬性。另外,當有列表時,這是更好的做法,因爲當出現驗證錯誤時,您不必重新填充它們。.NET MVC3優先模型初始化

舉例來說,如果我有以下型號:

public FooBarViewModel 
{ 
    public int FooBarId { get; set; } 
    public string SomeInitialProperty1 { get; set; } 
    public string SomeInitialProperty2 { get; set; } 
    public string SomeInitialProperty3 { get; set; } 
    public string SomeInitialProperty4 { get; set; } 
    public int FooId { get; set; } 
    public int BarId { get; set; } 
    public IEnumerable<Foo> Foos { get; set; } 
    public IEnumerable<Bar> Bars { get; set; } 
} 

,然後控制器:

public MyController : Controller 
{ 
    [HttpGet] 
    public ActionResult FooBar(int foobarId) 
    { 
     var foobar = _fooBarRepository.GetById(foobarId); 
     var model = new FooBarViewModel 
         { 
          FooBarId = foobar.Id; 
          SomeInitialProperty1 = foobar.SomeInitialProperty1; 
          SomeInitialProperty2 = foobar.SomeInitialProperty2; 
          SomeInitialProperty3 = foobar.SomeInitialProperty3; 
          SomeInitialProperty4 = foobar.SomeInitialProperty4; 
          Foos = foobar.Foos.ToList(); 
          Bars = foobar.Bars.ToList(); 
         } 

     return View(model); 
    } 

    [HttpPost] 
    public ActionResult FooBar(FooBarViewModel model) 
    { 
     if (ModelState.IsValid) 
     { 
      //process model 
      return RedirectToAction("Index"); 
     } 

     var foobar = _fooBarRepository.GetById(model.FoobarId); 
     model.Foos = foobar.GetFoos.ToList(); 
     model.Bars = foobar.GetBars.ToList(); 
     return View(model); 
    } 
} 

或者我應該做它在我的模型:

public FooBarViewModel 
{ 
    public int FooBarId { get; set; } 
    public string SomeInitialProperty1 { get; set; } 
    public string SomeInitialProperty2 { get; set; } 
    public string SomeInitialProperty3 { get; set; } 
    public string SomeInitialProperty4 { get; set; } 
    public int FooId { get; set; } 
    public int BarId { get; set; } 

    public IEnumerable<Foo> Foos 
    { 
     get { return _foos; } 
    } 
    private IEnumerable<Foo> _foos; 

    public IEnumerable<Bar> Bars 
    { 
     get { return _bars; } 
    } 
    private IEnumerable<Bar> _bars; 

    public MyViewModel(FooBar foobar) 
    { 
     FooBarId = foobar.Id; 
     SomeInitialProperty1 = foobar.SomeInitialProperty1; 
     SomeInitialProperty2 = foobar.SomeInitialProperty2; 
     SomeInitialProperty3 = foobar.SomeInitialProperty3; 
     SomeInitialProperty4 = foobar.SomeInitialProperty4; 
     _foos = foobar.Foos.ToList(); 
     _bars = foobar.Bars.ToList(); 
    } 
} 

然後我的控制器:

public MyController : Controller 
{ 
    [HttpGet] 
    public ActionResult FooBar(int foobarId) 
    { 
     var foobar = _fooBarRepository.GetById(foobarId); 
     var model = new FooBarViewModel(foobar); 

     return View(model); 
    } 

    [HttpPost] 
    public ActionResult FooBar(FooBarViewModelmodel) 
    { 
     if (ModelState.IsValid) 
     { 
      //process model 
      return RedirectToAction("Index"); 
     } 

     return View(model); 
    } 
} 

這是MVC中的首選約定,爲什麼它是最佳實踐?另外,爲什麼選擇一個在另一個之上的原因?提前致謝。

回答

4

默認情況下,我不相信MVC將使用DependencyResolver在回發中創建視圖模型的實例。因此,它只會創建一個帶無參數構造函數的模型。這使得在構造函數中初始化對象變得不那麼容易。

您可以創建一個通過DependencyResolver創建對象的自定義模型聯編程序,但那麼您會偏離正常實踐。

我寧願inialize我的看法型號AutoMapper。

+0

對於AutoMapper爲+1。在這裏學到了新東西。 –

+0

這看起來像一個很好的解決方案,看起來會節省時間。我將在我的項目中看看這個實現。謝謝。 – shuniar

4

一般來說,你想要重型車燈和燈光控制器,所以你儘可能少地在你的控制器。

一般設計模式的原因你應該初始化視圖模型中的ViewModel?

  • DRY - 如果有一個具有初始化視圖模型不止一個動作,你枯萎重複的代碼,或者你把它在控制器中的私有方法。對我而言,如果你需要在控制器中放置一個私有方法,這是一個相當有說服力的說明,即代碼完全不屬於控制器。
  • 凝聚力 - 一般情況下,一個Foo對象應該知道如何從其他對象實例化一個Foo對象,因爲它有知道關於自己的責任。將該邏輯放在其他地方會降低凝聚力並引入耦合。
3

我總是使用第二種方法,但使用「all-properties as parameters」 - 構造函數代替插入「Foobar」(違反了MVVM模式,因爲ViewModel應該保持獨立)。

對我來說這是最好的做法,因爲你可以在視圖模型中隱藏額外的邏輯,並且你有可能通過使用不同的構造函數來創建不同的行爲。

3

我認爲你在第二種情況下做得很好。在我看來,獲得一個可以使用的對象是該對象本身的責任。

如果您還需要另一個該類的其他實例,該怎麼辦?您必須首先從您創建的任何位置複製初始化代碼。