调用另一个控制器的动作 - 文件上传器的设计考虑 - MVC 4

par*_*ent 6 web-services command-pattern asp.net-mvc-4

我有一种情况,我正在讨论如何构建我的控制器.

考虑以下控制器:

    public class FileSharingController : Controller
    {

        private readonly ICommandBus commandBus;

        public FileSharingController(ICommandBus commandBus)
        {
            this.commandBus = commandBus;
        }

        [HttpPost]     
        public ActionResult PrepareMetadata(int blocksCount, string fileName, long fileSize)
        {
             ...
        }

        [HttpPost]
        public ActionResult ClearFileMetadata(string fileName){
            ...
        }

        [HttpPost] [ValidateInput(false)] //$.ajax({ data: html5FormDataFileChunk , processData: false ... })
        public ActionResult UploadBlock(string fileName, int blockId){

             var fileUploadCommand = (FileUploadCommand)ExtractFromSessionData(fileName);
             var result = commandBus.Submit(fileUploadCommand);
             ...
        }

        public ActionResult CommitFileUploads(string[] filesToCommit){
             var commitFileUploadCommand = (CommitFileUploadCommand)ExtractFromSessionData(fileName);
             var result = commandBus.Submit(commitFileUploadCommand );
             ...
        }
Run Code Online (Sandbox Code Playgroud)

在这个控制器中,我使用命令模式并将模型传递给我的commandBus,它与我的域接口.[HttpPost]控制器上的前三个方法用于处理来自响应文件上传UI的jQuery ajax调用.

考虑用户填写表单(面试)并上传一些文件的情况.虽然用户可以在提交表单之前上传文件,但我不希望上传文件提交,直到他们提交表单并通过验证.这就是控制器上的最后一个方法不是http端点的原因.因此,我有以下控制器:

    public class InterviewController : Controller
    {
        [HttpGet] 
        public ActionResult UserInterview()
        {
            InterviewViewModel viewModel = new InterviewViewModel ();
            return PartialView(viewModel);
        }

        [HttpPost] [AllowAnonymous]
        public ActionResult UserInterview(InterviewViewModel viewModel)
        {
            if(ModelState.IsValid)
            {
                var fileSharingController = new FileSharingController();
                fileSharingController.CommitFileUploads(viewModel.Files);
            }

            return PartialView(viewModel);
        }

    }
Run Code Online (Sandbox Code Playgroud)

问题是我正在使用IoC将一个commandBus注入到FileSharingController中,所以我不能像我一样用默认构造函数实例化它.

我可以考虑的选择:

  • 创建自定义控制器工厂以允许在代码中的任何位置实例化我的控制器.
  • 在WebAPI控制器中转动我的FileSharingController并将其视为服务

对于这种情况,哪条路线更好?如果是后一种情况,我怎样才能将CommitFileUploads()方法保密?我不希望它作为端点公开,可以在没有首先验证表单的其余部分的情况下触发.

Nen*_*nad 2

您可以像这样实例化您的控制器:

ICommandBus commandBus = DependencyResolver.Current.GetService<ICommandBus>();
var fileShareController = new FileSharingController(commandBus);
Run Code Online (Sandbox Code Playgroud)

通用 GetService() 方法是扩展方法,因此请确保您有“using System.Web.Mvc;” cs 文件中的行。

但是,最好有一个帮助程序类负责保存/存储已上传的文件,并从两个控制器调用它,而不是手动实例化控制器。

例如:

public class FileUploadManager
{
    public FileUploadManager(ICommandBus commandBus, HttpSessionStateBase sessionState)
    {
         //....
    }
}
Run Code Online (Sandbox Code Playgroud)

然后你称它为:

ICommandBus commandBus = DependencyResolver.Current.GetService<ICommandBus>();
var fileShareController = new FileUploadManager(commandBus, this.HttpContext.Session);
Run Code Online (Sandbox Code Playgroud)

或者,如果您不想使用 DependencyResolver,则可以将 ICommandBus 传递给两个控制器的构造函数,并使用该引用来实例化帮助程序类。