基本上,我有以下问题:
- 通常我喜欢有一个类/文件。 如果 ViewModel 仅被创建为从控制器到视图传递数据,这是否有意义?
- 如果 ViewModel 确实属于自己的文件,并且您正在使用目录/项目结构来保持事物分开,那么 ViewModel 文件应该放在哪里? 在 Controllers 目录中吗?
按类别(控制器、视图模型、过滤器等)分离类是无意义的。
如果你想为网站的首页部分(/)编写代码,那么创建一个名为Home的文件夹,将HomeController、IndexViewModel、AboutViewModel等所有与Home actions相关的类放在其中。
如果有共享类,比如一个ApplicationController,可以把它放在项目根目录下。
为什么要分离相关的东西(HomeController、IndexViewModel),而将毫不相关的东西放在一起(HomeController、AccountController)呢?
我写了一篇关于此主题的博客文章。
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类用于将多个数据对象封装为一个易于管理的对象,并将其传递给View。
最好将您的ViewModel类放在自己的文件中,在自己的目录中。在我的项目中,我有一个Models文件夹的子文件夹叫做ViewModels。这就是我的ViewModels(例如ProductViewModel.cs
)所在的位置。
没有一个好的地方来存储你的模型。如果项目很大并且有许多ViewModels(数据传输对象),则可以将它们放在单独的程序集中。此外,您还可以将它们放在站点项目的单独文件夹中。例如,在Oxite中,它们被放置在包含许多其他类的Oxite项目中。Oxite中的控制器已移至单独的项目中,视图也是如此。
在CodeCampServer中,ViewModels命名为*Form,并放置在UI项目的Models文件夹中。
在MvcPress项目中,它们被放置在Data项目中,该项目还包含所有与数据库交互的代码以及更多内容(但我不推荐这种方法,仅供参考)
因此,您可以看到有许多观点。通常,我将我的ViewModels(DTO对象)保存在站点项目中。但是,当我有超过10个模型时,我更喜欢将它们移到单独的程序集中。通常在这种情况下,我也会将控制器移动到单独的程序集中。
另一个问题是如何轻松地将所有数据从模型映射到ViewModel。我建议看看AutoMapper库。我非常喜欢它,它可以为我完成所有脏活。
我还建议看看SharpArchitecture项目。它为项目提供了非常好的架构,并且包含许多很酷的框架、指导和伟大的社区。
这是我最佳实践中的代码片段:
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");
}
}
我们将所有的ViewModel放在Models文件夹中(所有业务逻辑都在单独的ServiceLayer项目中)
个人建议,如果ViewModel不是微不足道的话,请使用单独的类。
如果您有多个ViewModel,则建议将其分区至少一个目录中。如果ViewModel稍后共享,则在目录中暗示的名称空间使其更容易移动到新的程序集中。
控制器中的代码:
[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(一个独立的类库项目)
在这个项目中,我创建了一些文件夹,如: DAL(数据访问层), BLL(业务逻辑层), BO(业务对象), VM(视图模型文件夹)