问题描述
我对 ASP.Net MVC 生疏,正在努力寻找正确的方法来解决我在继承的大型项目中遇到的情况。该应用程序有大量的控制器,这些控制器的角色最初是明确定义的。随着应用程序的发展,我遇到了它们之间功能重叠增加的问题。
例如,现在有一个仪表板控制器,可让用户概览整个应用程序其余部分发生的关键参数。因此,该控制器依赖于许多依赖项来填充视图。它还对仪表板所需的数据执行大量业务逻辑/计算。现在,我们有了新的附加要求,即在整个应用程序过程中的关键里程碑处将这些相同的值存档到数据库中。在使用仪表板视图时,这非常有效(它使用 ajax 并频繁调用更新) - 当我们达到这些里程碑时,我可以让它根据需要存储值。
但是当仪表板没有被使用时——并且没有调用仪表板视图/控制器,我们仍然需要将数据存储在里程碑处。我不想在可能达到各种里程碑的每个其他控制器中复制相同的逻辑,但我正在努力用所有必要的依赖项对其进行抽象。处理这个问题的最佳方法是什么?
[Authorize]
public class DashboardController : SdControllerBase
{
private readonly ICoLabAssembler _assembler;
private readonly ICoLabDataMapper _colabDataMapper;
private readonly IClusterassembler _clusterassembler;
private readonly IClusterDataMapper _clusterDataMapper;
private readonly IStatementDataMapper _statementDataMapper;
private readonly IStatementAssembler _statementAssembler;
private readonly IActiveCoLabIdService _activeCoLabIdService;
private readonly IIsmAlgorithmAdapterService _ismAdapter;
private readonly IPrioritizationVoteActionDataMapper _prioritizationVoteActionDataMapper;
private readonly IVoteDataMapper<PrioritizationVote,Participant> _prioritizationVoteDataMapper;
private readonly IPrincipal _currentUser;
private readonly SdContext _context;
private int? _activeColabId;
protected int ActiveColabId
{
get
{
_activeColabId = _activeColabId ?? _activeCoLabIdService.GetColabId();
return _activeColabId.Value;
}
}
public DashboardController(ICoLabAssembler assembler,ICoLabDataMapper dataMapper,IClusterassembler clusterassembler,IClusterDataMapper clusterDataMapper,IStatementDataMapper statementDataMapper,IStatementAssembler statementAssembler,IActiveCoLabIdService activeCoLabIdService,IPrioritizationVoteActionDataMapper prioritizationVoteActionDataMapper,IVoteDataMapper<PrioritizationVote,Participant> prioritizationVoteDataMapper,IPrincipal currentUser,IIsmAlgorithmAdapterService ismAdapter,SdContext context)
{
_assembler = assembler;
_colabDataMapper = dataMapper;
_clusterassembler = clusterassembler;
_clusterDataMapper = clusterDataMapper;
_statementDataMapper = statementDataMapper;
_statementAssembler = statementAssembler;
_activeCoLabIdService = activeCoLabIdService;
_prioritizationVoteActionDataMapper = prioritizationVoteActionDataMapper;
_prioritizationVoteDataMapper = prioritizationVoteDataMapper;
_currentUser = currentUser;
_ismAdapter = ismAdapter;
_context = context;
}
public async Task<ActionResult> Index()
{
var model = await buildDashboardviewmodelAsync();
return View(model);
}
[HttpPost]
public async Task<JsonResult> getDashboardAllData(int coLabID = 0)
{
var model = await buildDashboardviewmodelAsync(coLabID);
return Json(model,JsonRequestBehavior.AllowGet);
}
private async Task<CoLabDashboardviewmodel> buildDashboardviewmodelAsync(int coLabID = 0)
{
//Lots of business logic here that uses the dependencies above
return model;
}
解决方法
如果我可以从各种其他控制器调用仪表板控制器,我也许能够做出一个可行的解决方案,如果不是最优雅的。按照这个答案:How to call another controller Action From a controller in Mvc
添加到我的仪表板控制器:
public async void calculateMilestoneValues(int coLabID = 0)
{
//Used to calcualte and stored milestone values from other controllers.
var model = await buildDashboardViewModelAsync(coLabID);
return;
}
编辑: 在确定该项目已经在使用 Castle Windsor 之后,我终于能够获得一个可行的解决方案。我仍然需要为它设置一些额外的组件来解决依赖关系,但随后能够从其他控制器调用 DashboardController 中所需的功能:
//Call dashboard controller so it can save milestone data to db if needed
var dashboardController = ServiceLocator.GetContainer().Resolve<DashboardController>();
DashboardController.CalculateMilestoneValues(viewModel.CoLabId);
所以这并没有真正从控制器中抽象出功能,但它确实为我提供了一种调用它的方法,而无需将其复制到其他控制器中。