繁体   English   中英

使用Asp.Net MVC 5框架和IoC容器时,如何构造视图模型的实例?

[英]How to construct an instance of a view-model when using Asp.Net MVC 5 framework and IoC container?

我正在使用ASP.NET MVC 5框架以及Unity-Container编写一个项目来处理我的依赖项。

我正在寻找在Asp.Net MVC 5应用程序中使用IoC容器时处理构造视图模型的最佳实践。 我希望这个问题不被认为是基于观点的,并且可以解决。

我有以下视图模型类

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.....
    }
}

如您所见,我的CategoryReportViewModel类需要IUnitOfWork的实例,以允许我的方法执行其任务“除非我手动将IUnitOfWork传递给需要它的每个方法”。 我想知道什么是建立CategoryReportViewModel实例的正确方法。 是通过IoC容器还是通过旧方法通过构造函数传递IUnitOfWork实例?

换句话说,使用我的视图模型的正确方法是什么?

遵循这些是尝试应对这种情况时想到的方法,但是哪种方法正确? 也许还有其他选择?

一,老旧手工更新策略

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);
    }
}

第二,手动更新,但将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);
    }
}

第三,在注册CategoryReportViewModel之后使用IoC容器。 但是这将需要我修改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);
    }
}

在这方面可以有不同的方法和意见,但我发现最有效的模式是使ViewModels是“哑” DTO,其属性由控制器创建并填充。 将服务注入控制器,并在您的操作方法中包含所有业务逻辑。

换句话说, 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM