I have a situation where I'm debating how to architect 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 pattern and pass a model to my commandBus which interfaces with my domain. The first three [HttpPost]
methods on the controller are for handling jQuery ajax calls from a responsive file uploading UI.
Consider the situation where a user fills out a form (an interview) and uploads some files along with it. Although the user can upload the files before submitting the form, I don't want the uploaded files to be committed until AFTER they submit the form and it passes validation. That is why the last method on the controller is not an http endpoint. As such 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 I'm using IoC to inject a commandBus
into the FileSharingController so I cannot just instantiate it with default constructor as I am doing.
My options to consider:
Which is the better design path for this situation? If the latter case, how can I keep the CommitFileUploads()
method private? I don't want it to be exposed as an endpoint that can be triggered without first validating the rest of the form.
You can instantiate your controller like this:
ICommandBus commandBus = DependencyResolver.Current.GetService<ICommandBus>();
var fileShareController = new FileSharingController(commandBus);
Generic GetService() method is extension method, so make sure that you have "using System.Web.Mvc;" line in the cs file.
But then, it's better to have helper class that is responsible for keeping/storing already uploaded files, and call it from both controllers, instead instantiating controllers manually.
For example:
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 don't want to use DependencyResolver, you pass ICommandBus to both controller's constructors, and use that reference to instantiate helper class.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With