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

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

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

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

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


当前回答

在我们的例子中,我们将模型和控制器放在一个独立于视图的项目中。

根据经验,我们已经尝试移动和避免大多数ViewData[”…]的东西,因此我们避免了类型转换和魔术字符串,这是一件好事。

ViewModel还包含一些常见的属性,如列表的分页信息或用于绘制面包屑和标题的页眉信息。在我看来,此时基类包含了太多的信息,我们可以将其分为三部分,基本视图模型中99%的页面的最基本和必要的信息,然后是列表模型和表单模型,其中包含了该场景的特定数据并继承自基类。

最后,我们为每个实体实现一个视图模型来处理特定的信息。

其他回答

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

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

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

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类用于将由类实例表示的多个数据封装到一个易于管理的对象中,您可以将该对象传递给View。

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

控制器中的代码:

    [HttpGet]
        public ActionResult EntryEdit(int? entryId)
        {
            ViewData["BodyClass"] = "page-entryEdit";
            EntryEditViewModel viewMode = new EntryEditViewModel(entryId);
            return View(viewMode);
        }

    [HttpPost]
    public ActionResult EntryEdit(Entry entry)
    {
        ViewData["BodyClass"] = "page-entryEdit";            

        #region save

        if (ModelState.IsValid)
        {
            if (EntryManager.Update(entry) == 1)
            {
                return RedirectToAction("EntryEditSuccess", "Dictionary");
            }
            else
            {
                return RedirectToAction("EntryEditFailed", "Dictionary");
            }
        }
        else
        {
            EntryEditViewModel viewModel = new EntryEditViewModel(entry);
            return View(viewModel);
        }

        #endregion
    }

视图模型中的代码:

public class EntryEditViewModel
    {
        #region Private Variables for Properties

        private Entry _entry = new Entry();
        private StatusList _statusList = new StatusList();        

        #endregion

        #region Public Properties

        public Entry Entry
        {
            get { return _entry; }
            set { _entry = value; }
        }

        public StatusList StatusList
        {
            get { return _statusList; }
        }

        #endregion

        #region constructor(s)

        /// <summary>
        /// for Get action
        /// </summary>
        /// <param name="entryId"></param>
        public EntryEditViewModel(int? entryId)
        {
            this.Entry = EntryManager.GetDetail(entryId.Value);                 
        }

        /// <summary>
        /// for Post action
        /// </summary>
        /// <param name="entry"></param>
        public EntryEditViewModel(Entry entry)
        {
            this.Entry = entry;
        }

        #endregion       
    }

项目:

DevJet。Web (ASP。NET MVC web 项目) DevJet.Web.App.Dictionary (a 单独的类库项目) 在这个项目中,我做了一些文件夹,比如: 木豆, BLL, 薄 VM(视图模型文件夹)

下面是我的最佳实践代码片段:

    public class UserController : Controller
    {
        private readonly IUserService userService;
        private readonly IBuilder<User, UserCreateInput> createBuilder;
        private readonly IBuilder<User, UserEditInput> editBuilder;

        public UserController(IUserService userService, IBuilder<User, UserCreateInput> createBuilder, IBuilder<User, UserEditInput> editBuilder)
        {
            this.userService = userService;
            this.editBuilder = editBuilder;
            this.createBuilder = createBuilder;
        }

        public ActionResult Index(int? page)
        {
            return View(userService.GetPage(page ?? 1, 5));
        }

        public ActionResult Create()
        {
            return View(createBuilder.BuildInput(new User()));
        }

        [HttpPost]
        public ActionResult Create(UserCreateInput input)
        {
            if (input.Roles == null) ModelState.AddModelError("roles", "selectati macar un rol");

            if (!ModelState.IsValid)
                return View(createBuilder.RebuildInput(input));

            userService.Create(createBuilder.BuilEntity(input));
            return RedirectToAction("Index");
        }

        public ActionResult Edit(long id)
        {
            return View(editBuilder.BuildInput(userService.GetFull(id)));
        }

        [HttpPost]
        public ActionResult Edit(UserEditInput input)
        {           
            if (!ModelState.IsValid)
                return View(editBuilder.RebuildInput(input));

            userService.Save(editBuilder.BuilEntity(input));
            return RedirectToAction("Index");
        }
}