从这个问题来看,让控制器创建一个更准确地反映视图试图显示的模型的ViewModel似乎是有意义的,但我对一些约定很好奇。

基本上,我有以下几个问题:

我通常喜欢有一个类/文件。如果创建ViewModel只是为了将数据从控制器传递给视图,那么这对ViewModel有意义吗? 如果ViewModel属于它自己的文件,并且您正在使用目录/项目结构来保持内容分离,那么ViewModel文件属于哪里?在Controllers目录下?

现在基本上就是这样了。我可能会有更多的问题,但这已经困扰了我一个小时左右,我似乎可以在其他地方找到一致的指导。

编辑: 查看CodePlex上的示例NerdDinner应用程序,它看起来像视图模型是控制器的一部分,但它仍然让我不舒服,因为它们不在自己的文件中。


当前回答

我将我的应用程序类保存在一个名为“Core”的子文件夹中(或一个单独的类库),并使用与KIGG示例应用程序相同的方法,但做了一些轻微的更改,以使我的应用程序更加DRY。

我在/Core/ViewData/中创建了一个BaseViewData类,其中存储了常见的站点属性。

在此之后,我还在同一个文件夹中创建了所有的视图ViewData类,然后从BaseViewData派生并具有视图特定的属性。

然后我创建一个ApplicationController,我所有的控制器都是从它派生出来的。ApplicationController有一个通用的GetViewData方法,如下:

protected T GetViewData<T>() where T : BaseViewData, new()
    {
        var viewData = new T
        {
           Property1 = "value1",
           Property2 = this.Method() // in the ApplicationController
        };
        return viewData;
    }

最后,在我的控制器动作中,我做以下工作来构建我的ViewData模型

public ActionResult Index(int? id)
    {
        var viewData = this.GetViewData<PageViewData>();
        viewData.Page = this.DataContext.getPage(id); // ApplicationController
        ViewData.Model = viewData;
        return View();
    }

我认为这工作得很好,它保持你的视图整洁,你的控制器瘦。

其他回答

按类别划分类(控制器、视图模型、过滤器等)是毫无意义的。

如果你想为你的网站(/)的Home部分写代码,然后创建一个名为Home的文件夹,并在那里放置HomeController, IndexViewModel, AboutViewModel等,以及Home操作使用的所有相关类。

如果你有共享类,比如ApplicationController,你可以把它放在项目的根目录。

为什么要分离相关的东西(HomeController, IndexViewModel),而把完全没有关系的东西放在一起(HomeController, AccountController) ?


我就这个话题写了一篇博客。

我将我的应用程序类保存在一个名为“Core”的子文件夹中(或一个单独的类库),并使用与KIGG示例应用程序相同的方法,但做了一些轻微的更改,以使我的应用程序更加DRY。

我在/Core/ViewData/中创建了一个BaseViewData类,其中存储了常见的站点属性。

在此之后,我还在同一个文件夹中创建了所有的视图ViewData类,然后从BaseViewData派生并具有视图特定的属性。

然后我创建一个ApplicationController,我所有的控制器都是从它派生出来的。ApplicationController有一个通用的GetViewData方法,如下:

protected T GetViewData<T>() where T : BaseViewData, new()
    {
        var viewData = new T
        {
           Property1 = "value1",
           Property2 = this.Method() // in the ApplicationController
        };
        return viewData;
    }

最后,在我的控制器动作中,我做以下工作来构建我的ViewData模型

public ActionResult Index(int? id)
    {
        var viewData = this.GetViewData<PageViewData>();
        viewData.Page = this.DataContext.getPage(id); // ApplicationController
        ViewData.Model = viewData;
        return View();
    }

我认为这工作得很好,它保持你的视图整洁,你的控制器瘦。

就我个人而言,我建议如果ViewModel不是微不足道的,那么使用一个单独的类。

如果你有多个视图模型,那么我建议至少在一个目录中划分它。如果稍后共享视图模型,则目录中隐含的名称空间可以更容易地移动到新的程序集。

我为每个视图创建了所谓的“ViewModel”。我把它们放在MVC Web项目中一个名为ViewModels的文件夹中。我根据它们所代表的控制器和动作(或视图)来命名它们。所以如果我需要传递数据到会员控制器上的注册视图,我创建了一个MembershipSignUpViewModel.cs类,并把它放在ViewModels文件夹中。

然后我添加必要的属性和方法,以促进数据从控制器传输到视图。我使用Automapper从我的ViewModel到域模型,如果需要的话再返回。

这也适用于包含其他viewmodel类型属性的复合viewmodel。例如,如果你在成员控制器的索引页上有5个小部件,并且你为每个分部视图创建了一个ViewModel——你如何将数据从index动作传递给分部?你在MembershipIndexViewModel中添加一个MyPartialViewModel类型的属性,当呈现部分时,你将在Model.MyPartialViewModel中传递。

这样做允许您调整部分ViewModel属性,而不必更改Index视图。它仍然只是传入模型。MyPartialViewModel所以当你所做的只是向partial ViewModel添加一个属性时,你就不太可能需要通过整个partial链来修复一些东西。

我还将添加命名空间“MyProject.Web”。ViewModels”到网络。配置,以便允许我在任何视图中引用它们,而无需在每个视图上添加显式的import语句。只是让它更干净一点。

ViewModel类用于将由类实例表示的多个数据封装到一个易于管理的对象中,您可以将该对象传递给View。

将ViewModel类放在自己的文件中,放在自己的目录中是有意义的。在我的项目中,我有一个名为ViewModels的Models文件夹子文件夹。这就是我的ViewModels(例如ProductViewModel.cs)所在的位置。