2011-09-29 71 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

相关问题