[英]How to construct an instance of a view-model when using Asp.Net MVC 5 framework and IoC container?
I am writing a project using ASP.NET MVC 5 framework along with Unity-Container to handle my dependencies. 我正在使用ASP.NET MVC 5框架以及Unity-Container编写一个项目来处理我的依赖项。
I am hunting for a best practice to deal with constructing view-models while using IoC
container in an Asp.Net MVC 5 app. 我正在寻找在Asp.Net MVC 5应用程序中使用IoC
容器时处理构造视图模型的最佳实践。 I hope this question isn't considered opinion based and gets closed. 我希望这个问题不被认为是基于观点的,并且可以解决。
I have the following view-model class 我有以下视图模型类
public class CategoryReportViewModel
{
public IUnitOfWork UnitOfWork { get; set; }
public IEnumerable<object> Records { get; set; }
// ....
public TasksSummaryByProductViewModel(IUnitOfWork unitOfWork)
{
UnitOfWork = unitOfWork;
}
public void SetFilters()
{
// Do something.....
UnitOfWork.....
}
public void SetData()
{
// Do something.....
Records = UnitOfWork.....
}
}
As you can see, my CategoryReportViewModel
class needs an instance of the IUnitOfWork
to allow my methods to to perform their task "unless I manually pass the IUnitOfWork
to every method that needs it." 如您所见,我的CategoryReportViewModel
类需要IUnitOfWork
的实例,以允许我的方法执行其任务“除非我手动将IUnitOfWork
传递给需要它的每个方法”。 I am wondering what is the right way to new up an instance of CategoryReportViewModel
. 我想知道什么是建立CategoryReportViewModel
实例的正确方法。 Is it via IoC
container or using the good-old way by passing an instance of the IUnitOfWork
from the constructor? 是通过IoC
容器还是通过旧方法通过构造函数传递IUnitOfWork
实例?
In other words, what is the right way to consume my view-model? 换句话说,使用我的视图模型的正确方法是什么?
Follow are the approaches that comes to mind when trying to deal with this scenario, but which is the right way? 遵循这些是尝试应对这种情况时想到的方法,但是哪种方法正确? Perhaps there is alternative? 也许还有其他选择?
First, good-old manual new up strategy 一,老旧手工更新策略
public class ReportsController : Controller
{
protected IUnitOfWork UnitOfWork { get; set; }
public ReportsController(IUnitOfWork unitOfWork)
{
UnitOfWork = unitOfWork;
}
[HttpGet]
public ActionResult CategoryByName()
{
var viewModel = new CategoryReportViewModel(UnitOfWork);
viewModel.SetFilters();
return View(viewModel);
}
[HttpPost, ValidateAntiForgeryToken]
public ActionResult CategoryByName(CategoryReportViewModel viewModel)
{
viewModel.UnitOfWork = UnitOfWork; // This is ugly
if (ModelState.IsValid)
{
viewModel.SetData();
}
viewModel.SetFilters();
return View(viewModel);
}
}
Second, manual new up but pass the UnitOfWork
to any methods that needs it 第二,手动更新,但将UnitOfWork
传递给需要它的任何方法
public class ReportsController : Controller
{
protected IUnitOfWork UnitOfWork { get; set; }
public ReportsController(IUnitOfWork unitOfWork)
{
UnitOfWork = unitOfWork;
}
[HttpGet]
public ActionResult CategoryByName()
{
var viewModel = new CategoryReportViewModel();
viewModel.SetFilters();
return View(viewModel);
}
[HttpPost, ValidateAntiForgeryToken]
public ActionResult CategoryByName(CategoryReportViewModel viewModel)
{
if (ModelState.IsValid)
{
viewModel.SetData(UnitOfWork);
}
viewModel.SetFilters(UnitOfWork);
return View(viewModel);
}
}
Third, using IoC
container after registering the CategoryReportViewModel
. 第三,在注册CategoryReportViewModel
之后使用IoC
容器。 But this will require me to modify Asp.Net MVC 5 default behavior since my view-model may/does not have a default constructor. 但是这将需要我修改Asp.Net MVC 5的默认行为,因为我的视图模型可能/没有默认构造函数。
public class ReportsController : Controller
{
[HttpGet]
public ActionResult CategoryByName()
{
var viewModel = DependencyResolver.Current.GetService<CategoryReportViewModel>();
viewModel.SetFilters();
return View(viewModel);
}
// This will now work since I my view-model does not have a default constructor
// unless I override the `DefaultModelBinder` class somehow to resolve the class
// from the IoC container
[HttpPost, ValidateAntiForgeryToken]
public ActionResult CategoryByName(CategoryReportViewModel viewModel)
{
if (ModelState.IsValid)
{
viewModel.SetData();
}
viewModel.SetFilters();
return View(viewModel);
}
}
There's room for different approaches and opinions on this, but the pattern I've found to work best is to make the ViewModels be "dumb" DTOs whose properties are created and populated by the controller. 在这方面可以有不同的方法和意见,但我发现最有效的模式是使ViewModels是“哑” DTO,其属性由控制器创建并填充。 Inject services into the controller, and have all the business logic in your action methods. 将服务注入控制器,并在您的操作方法中包含所有业务逻辑。
In other words, SetFilters()
and SetData()
should probably be on the controller, and take the model as an argument. 换句话说, SetFilters()
和SetData()
可能应该在控制器上,并将模型作为参数。
public class ReportsController : Controller
{
protected IUnitOfWork UnitOfWork { get; set; }
public ReportsController(IUnitOfWork unitOfWork)
{
UnitOfWork = unitOfWork;
}
[HttpGet]
public ActionResult CategoryByName()
{
var viewModel = new CategoryReportViewModel();
this.SetFilters(viewModel);
return View(viewModel);
}
[HttpPost, ValidateAntiForgeryToken]
public ActionResult CategoryByName(CategoryReportViewModel viewModel)
{
if (ModelState.IsValid)
{
this.SetData(viewModel);
}
this.SetFilters(viewModel);
return View(viewModel);
}
private void SetFilters(CategoryReportViewModel viewModel)
{
// Do something.....
UnitOfWork.....
}
private void SetData(CategoryReportViewModel viewModel)
{
// Do something.....
Records = UnitOfWork.....
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.