簡體   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