As a fairly experienced ASP.Net developer just recently starting using MVC, I find myself struggling a bit to change my mindset from a traditional "server control and event handler" way of doing things, into the more dynamic MVC way of things. I think I am slowly getting there, but sometimes the MVC "magic" throws me off.
My current scenario is to create a web page that allows the user to browse a local file, upload it to the server and repeat this until he has a list of files to work with. When he is happy with the file list (which will be displayed in a grid on the page), he will click a button to process the files and extract some data that will be stored in a database.
The last part is not so important, right now I am struggling with something as trivial as building up a list of files, and persisting that list between requests. In the traditional approach this would be extremely simple - the data would be persisted in ViewState. But in MVC I need to pass the data between the controller and the views, and I don't fully get how this is supposed to work.
I guess I better post my rather incomplete attempt of coding this to explain the problem.
In order to keep my file list data, I have created a viewmodel that is basically a typed list of files, along with some extra metadata:
public class ImportDataViewModel
{
public ImportDataViewModel()
{
Files = new List<ImportDataFile>();
}
public List<ImportDataFile> Files { get; set; }
...
In the view, I have a form for browsing and uploading the file:
<form action="AddImportFile" method="post" enctype="multipart/form-data">
<label for="file">
Filename:</label>
<input type="file" name="file" id="file" />
<input type="submit" />
</form>
The view is using the viewmodel as its model:
@model MHP.ViewModels.ImportDataViewModel
This will send the file to my action:
public ActionResult AddImportFile(HttpPostedFileBase file, ImportDataViewModel importData)
{
if (file.ContentLength > 0)
{
ImportDataFile idFile = new ImportDataFile { File = file };
importData.Files.Add(idFile);
}
return View("DataImport", importData);
}
This action returns the view for the DataImport page along with the viewmodel instance containing the list of files.
This works nicely up to a certain point, I can browse a file and upload it, and I can see the viewmodel data inside the action, and then also if I put a breakpoint inside the view and debug "this.Model", everything is fine.
But then, if I try to upload another file, when putting a breakpoint inside the AddImportFile action, the importData parameter is empty. So the view is obviously not passing the current instance of its model to the action.
In the MVC samples I have been through, the model instance is "magically" passed to the action method as a parameter, so why is it empty now?
I assume the real problem is my limited understanding of MVC, and that there is probably a very simple solution to this. Anyways, I would be extremely grateful if somebody could point me in the right direction.
See Question&Answers more detail:
os