Invoking another controller action - Design Considerations for File Uploader - MVC 4

I have a situation where I am discussing how to archive my controllers.

Consider the following controller:

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

In this controller, I use the command template and pass the model to my commandBus, which interacts with my domain. The first three [HttpPost] on the controller are designed to handle jQuery ajax calls from the user user interface.

Consider a situation where a user fills out a form (interview) and uploads some files with it. Although the user can upload files before submitting the form, I donโ€™t want the downloaded files to be committed until they submit the form and validate. This is why the last method on the controller is not the http endpoint. Therefore, I have the following controller:

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

The problem is that I use IoC to enter the commandBus in the FileSharingController, so I cannot just create an instance with the default constructor, as I do.

My options are:

  • Create a custom factory controller to allow an instance of my controller anywhere in the code.
  • Turn my FileSharingController into a WebAPI controller and see how the service

What is the best design path for this situation? If in the latter case, how can I keep the CommitFileUploads() method private? I do not want it to appear as an endpoint that can be launched without first checking the rest of the form.

+6
source share
2 answers

You can create an instance of your controller as follows:

 ICommandBus commandBus = DependencyResolver.Current.GetService<ICommandBus>(); var fileShareController = new FileSharingController(commandBus); 

The general GetService () method is an extension method, so make sure you have "using System.Web.Mvc;" line in the cs file.

But then it is better to have a helper class that is responsible for saving / saving already loaded files and calling it from both controllers, instead creating manual copies of the controllers.

For instance:

 public class FileUploadManager { public FileUploadManager(ICommandBus commandBus, HttpSessionStateBase sessionState) { //.... } } 

and then you call it:

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

Or, if you do not want to use DependencyResolver, you pass ICommandBus to both controller constructors and use this link to instantiate the helper class.

+2
source

just simply create an object of another controller and use all its public methods.

0
source

All Articles