简体   繁体   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?

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.

相关问题 如何在列表中添加多个记录以及视图模型Linq中的其他模型-ASP.NET-MVC5 - How to add multiple records in List along with other model in view-model Linq - ASP.NET-MVC5 如何使用视图模型在asp.net mvc 5中进行编辑? - how to edit in asp.net mvc 5 using view model? 标准化存储库,UnitOfWork,IOC容器Asp.Net MVC - Standardize Repository, UnitOfWork, IOC Container Asp.Net MVC 如何从ASP.NET MVC 5应用程序中的“区域”在IoC容器中注册类型? - How to register type in the IoC container from an “Area” in ASP.NET MVC 5 app? 使用ASP.NET MVC时如何在视图中显示数据表? - How to Display DataTables in a View when using ASP.NET MVC? 在ASP.net解决方案中使用Unity IOC容器 - Using Unity IOC Container in ASP.net solution 如何在ASP.NET中使用IoC容器配置单元测试? - How to configure unit tests with an IoC container in ASP.NET? ASP.Net MVC错误验证-将自定义视图模型传递给视图时如何显示验证消息 - ASP.Net MVC Error Validation - How to display validation message when passing a custom view model to a view 如何使用ASP.NET MVC框架将Datagrid数据源分配给模型 - How to assign Datagrid DataSource to Model with ASP.NET MVC FrameWork 如何在Asp.net MVC 5中填充没有实体框架的模型 - How to populate a model without entity framework in Asp.net MVC 5
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM