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

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

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

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

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


当前回答

创建一个视图模型基类,它具有通常需要的属性,如操作结果和上下文数据,您还可以放置当前用户数据和角色

class ViewModelBase 
{
  public bool HasError {get;set;} 
  public string ErrorMessage {get;set;}
  public List<string> UserRoles{get;set;}
}

在基控制器类中,有一个类似PopulateViewModelBase()的方法,该方法将填充上下文数据和用户角色。 HasError和ErrorMessage,如果从service/db中提取数据时出现异常,请设置这些属性。在视图上绑定这些属性以显示错误。 用户角色可用于根据角色在视图中显示隐藏部分。

要在不同的get操作中填充视图模型,可以通过具有具有抽象方法FillModel的基本控制器使之一致

class BaseController :BaseController 
{
   public PopulateViewModelBase(ViewModelBase model) 
{
   //fill up common data. 
}
abstract ViewModelBase FillModel();
}

在控制器

class MyController :Controller 
{

 public ActionResult Index() 
{
   return View(FillModel()); 
}

ViewModelBase FillModel() 
{ 
    ViewModelBase  model=;
    string currentAction = HttpContext.Current.Request.RequestContext.RouteData.Values["action"].ToString(); 
 try 
{ 
   switch(currentAction) 
{  
   case "Index": 
   model= GetCustomerData(); 
   break;
   // fill model logic for other actions 
}
}
catch(Exception ex) 
{
   model.HasError=true;
   model.ErrorMessage=ex.Message;
}
//fill common properties 
base.PopulateViewModelBase(model);
return model;
}
}

其他回答

我们将所有的viewmodel都放在Models文件夹中(所有的业务逻辑都在一个单独的ServiceLayer项目中)

创建一个视图模型基类,它具有通常需要的属性,如操作结果和上下文数据,您还可以放置当前用户数据和角色

class ViewModelBase 
{
  public bool HasError {get;set;} 
  public string ErrorMessage {get;set;}
  public List<string> UserRoles{get;set;}
}

在基控制器类中,有一个类似PopulateViewModelBase()的方法,该方法将填充上下文数据和用户角色。 HasError和ErrorMessage,如果从service/db中提取数据时出现异常,请设置这些属性。在视图上绑定这些属性以显示错误。 用户角色可用于根据角色在视图中显示隐藏部分。

要在不同的get操作中填充视图模型,可以通过具有具有抽象方法FillModel的基本控制器使之一致

class BaseController :BaseController 
{
   public PopulateViewModelBase(ViewModelBase model) 
{
   //fill up common data. 
}
abstract ViewModelBase FillModel();
}

在控制器

class MyController :Controller 
{

 public ActionResult Index() 
{
   return View(FillModel()); 
}

ViewModelBase FillModel() 
{ 
    ViewModelBase  model=;
    string currentAction = HttpContext.Current.Request.RequestContext.RouteData.Values["action"].ToString(); 
 try 
{ 
   switch(currentAction) 
{  
   case "Index": 
   model= GetCustomerData(); 
   break;
   // fill model logic for other actions 
}
}
catch(Exception ex) 
{
   model.HasError=true;
   model.ErrorMessage=ex.Message;
}
//fill common properties 
base.PopulateViewModelBase(model);
return model;
}
}

我将我的应用程序类保存在一个名为“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();
    }

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

There are no good place to keep your models in. You can keep them in separate assembly if the project is big and there are a lot of ViewModels (Data Transfer Objects). Also you can keep them in separate folder of the site project. For example, in Oxite they are placed in Oxite project which contains a lot of various classes too. Controllers in Oxite are moved to separate project and views are in separate project too. In CodeCampServer ViewModels are named *Form and they are placed in UI project in Models folder. In MvcPress project they are placed in Data project, which also contains all code to work with database and a bit more (but I didn't recommend this approach, it's just for a sample) So you can see there are many point of view. I usually keep my ViewModels (DTO objects) in the site project. But when I have more than 10 models I prefer to move them to separate assembly. Usually in this case I'm moving controllers to separate assembly too. Another question is how to easily map all data from model to your ViewModel. I suggest to have a look at AutoMapper library. I like it very much, it does all dirty work for me. And I also I suggest to look at SharpArchitecture project. It provides very good architecture for projects and it contains a lot of cool frameworks and guidances and great community.

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

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

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

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


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