2011-09-29 41 views
3

我有以下視圖模型:最佳的方法來填充的SelectList的視圖模型上的GET/POST

public class EditViewModel 
{ 
    public int FooType { get; set; } 
    public IEnumerable<SelectListItem> FooTypes { get; set; } 
} 

我本來居住在我的編輯操作,像這樣:

public ActionResult Edit(int id) 
{ 
    EditViewModel model = new EditViewModel(); 
    model.FooTypes = new SelectList(repository.GetFooTypes(), "Id", "Value"); 

    return View(model); 
} 

當我創建的操作POST的價值,我不得不重複相同的代碼:

public ActionResult Edit(int id, EditViewModel model) 
{ 
    if(!ModelState.IsValid) 
    { 
     model.FooTypes = new SelectList(repository.GetFooTypes(), "Id", "Value"); 

     return View(model); 
    } 

    return RedirectToAction("Index"); 
} 

我不喜歡有這個代碼在兩個不同的位置。是否有任何常見的做法將其重構爲單個點,所以我不需要重複此代碼?

回答

0

鑑於c#是面向對象的語言,有很多選項可用。

最簡單的是隻敷在控制器內的方法:

private SelectList GetFooTypesList() 
{ 
    return new SelectList(repository.GetFooTypes(), "Id", "Value); 
} 

,並把它設置你的模型時

,或者如果你在多個類中使用它你可以在另一個接受存儲庫或IEnumerable作爲參數的類中創建一個輔助方法。

如果你想要得到真正的高級,你可以使用ModelFactory爲你創建FooType模型,並預先填充FooType屬性,這樣控制器根本就不用擔心它。

有大量的選項,你只需要選擇一個最適合你的。

我個人的偏好是在控制器的簡單的輔助方法。

0

我在之前的模型做了(當時是該項目組編碼的做法),但要看在什麼是「商業邏輯」的理念,什麼是「數據訪問」,並在屬於什麼模型vs控制器。存在不同且合理的意見。

型號,在這裏你需要FooType可空類型:

public class EditViewModel 
{ 
    public int? FooType { get; set; } 
    public IEnumerable<SelectListItem> GetFooTypes(object selectedFooType = null) 
    { 
     return new SelectList(repository.GetFooTypes(), "Id", "Value", selectedFooType); 
    } 
} 

「獲取」控制器,你需要首先創建模型,以確保Model屬性在視圖可用:

public ActionResult Edit(int id) 
{ 
    EditViewModel model = new EditViewModel(); 

    return View(model); 
} 

的視圖(SANS芭芭拉瓦瓦):

@Html.DropDownListFor(m => m.FooType, Model.GetFooTypes(Model.FooType)) 

,是以 「觀點的東西」 出來的模型的替代看起來可能是這樣:

型號:

public class EditViewModel 
{ 
    public int? FooType { get; set; } 
    public IEnumerable<int?> FooTypes 
    { 
     get 
     { 
      // declare/define repository in your model somewhere  
      return repository.GetFooTypes(); 
     } 
    } 
} 

查看:

@Html.DropDownListFor(m => m.FooType, new SelectList(Model.FooTypes, "Id", "Value", Model.FooType)) 
0

在答覆 「nekno」 (回答9月30日22:19),有兩個ViewModel的替代品,它返回'IEnumerable <SelectListItem>'或'IEnumerable < int? >'。 這兩種替代方法都使用一個存儲庫,但實際上並沒有創建它,所以我想稍微擴展代碼示例,並選擇第二種替代方法,即類型爲'IEnumerable < int的類? >':

using Microsoft.Practices.ServiceLocation; // ServiceLocator , http://commonservicelocator.codeplex.com/ 
using MyOwnRepositoryNameSpace; // IRepository 
public class EditViewModel 
{ 
    public int? FooType { get; set; } 

    public IEnumerable<int?> FooTypes 
    { 
     get 
     { 
      return Repository.GetFooTypes(); 
     } 
    } 

    private IRepository Repository 
    { 
     get 
     { 
      return ServiceLocator.Current.GetInstance<IRepository>(); 
     } 
    } 
} 

上面種代碼以‘Dependecy查找’現在使用一個依賴於第三部分文庫,在此情況下常見服務定位器庫。

我的問題是如何將上述代碼替換爲「依賴注入」? 視圖模型本身確實是很容易實現的,就像這樣:

using MyOwnRepositoryNameSpace; // IRepository 
public class EditViewModel 
{ 
    private readonly IRepository _repository; 

    public EditViewModel(IRepository repository) 
    { 
     _repository = repository; 
    } 

    public int? FooType { get; set; } 

    public IEnumerable<int?> FooTypes 
    { 
     get 
     { 
      return _repository.GetFooTypes(); 
     } 
    } 
} 

的問題是如何使視圖模型成爲一個實現,當ASP.NET MVC框架將實例化「EditViewModel」注入並把它作爲一個參數一個動作的方法,如tihs方法簽名:

public ActionResult Edit(int id, EditViewModel model) { 
// How do we make the framework instantiate the above 'EditViewModel' with an implementation of 'IRepository' when the Action method is invoked ??? 

官方的MVC教程似乎並不遠,我可以看到提供任何很好的解決方案。 在下面的頁面中的「處理編輯」(方法'public ActionResult Edit(...)')一節中,他們以與您正在閱讀的此計算器問題的海報類似的方式複製選項的創建。

http://www.asp.net/mvc/tutorials/mvc-music-store/mvc-music-store-part-5

http://mvcmusicstore.codeplex.com/SourceControl/changeset/view/d9f25c5263ed#MvcMusicStore%2fControllers%2fStoreManagerController.cs

如果有一個關於如何使框架注入視圖模型與您的數據獵犬(如倉庫)解決方案,那麼我認爲它可能是使用的一些實現中或者'IModelBinderProvider'或'IModelBinder',但我已經嘗試過這些沒有真正的成功...

因此,任何人都可以提供一個鏈接到一個完整的工作示例與ASP。NET MVC 3代碼,它允許將數據檢索器注入到框架實例化的視圖模型的構造器中,並將其作爲參數發送到動作方法中?

更新2012-01-01: 對於那些在溶液intrested約一個ViewModel實例的構造函數注入這個具體問題,當框架實例化它,將它作爲參數傳遞到MVC操作方法的參數,我已經創建了一個更具體的主題的新問題,因此希望更有可能的解決方案的人會找到它併發佈一個很好的答案: Constructor injection of a View Model instance used as an Action method parameter