Quantcast
Viewing all articles
Browse latest Browse all 9364

Berin Loritsch: Asp.Net MVC 2 Uploading Files

In my opinion, of all the web frameworks I’ve used Ruby on Rails is the most pleasurable to develop with. It’s the yardstick I measure other frameworks by. I haven’t used them all, so there may actually be something nicer out there. I know Apache Wicket isn’t it, nor is Asp.Net MVC 2. However, for the respective platforms (Java and .Net respectively), they are as close as I’ve seen. Some parts are over-engineered (ahem, MVC authentication…) and other parts are broken (ahem… Microsoft’s development web server server and serializing objects across DLL boundaries). Taken as a whole, Asp.Net MVC is pretty good.

Now, in an application I’m working I need to upload files through the web browser. The task is quite a bit easier than my experiences with the same task in the Java environment. For one, the Asp.Net team didn’t ignore the “multipart/form-data” protocol that’s part of the HTTP and HTML spec. So, bear with me while I review some topics you can find at Scott Hanselman’s blog but I have a new twist I haven’t found in someone else’s article yet. In order for a browser to submit files to a server, you have to use HTML that looks like this:


<form action="#" method="post" enctype="multipart/form-data">
<div>
  <input type="file" name="UploadThis"/>
  <input type="submit" value="Submit"/>
</div>
</form> 

The two most important requirements are the “method” and “enctype” attributes on the form markup. If method is not “post” then the browser will ignore the encoding attribute and encode the form values in the URL. If the enctype is not “multipart/form-data” the browser won’t know how to encode the file into the HTTP request. The server will only get the filename and not the content of the file.

There’s no special features for MVC .Net to create the form elements and input elements like there is for text boxes and the like. The article by A.Sethi provides some markup in Asp.Net speak:


<% using (Html.BeginForm("Upload", "File", FormMethod.Post,
                    new { enctype = "multipart/form-data" }))
    {%>
        <p><input type="file" name="UploadThis"></p>
        <p><input type="submit" value="Submit" /></p>        
<% } %>   

Now, where this little review is going to diverge is we are going to actually write a model to handle the file upload. A.Sethi and Scott Hanselman both look at the Request.Files property and cycle through the values there. It works, but it’s not making the most of the MVC framework. It turns out that if you use the same type that is defined in the Request.Files property in our model, MVC knows what to do with it. So let’s create our file upload model:


namespace example.Models
{
    public class UploadModel
    {
        [Required]
        public HttpPostedFile UploadThis { get; set; }
    }
}

As long as the file input name matches the property name on the model, it will be populated by the framework. In the controller, we would simply use an action that looks like this:


    [HttpPost]
    public AcionResult UploadFile(UploadModel upload)
    {
        if(ModelState.IsValid)
        {
            string filePath = Path.Combine(
                HttpContext.Server.MapPath("../Uploads"),
                Path.GetFileName(upload.UploadThis.FileName));
            upload.UploadThis.SaveAs(filePath);

            return RedirectToAction("Index");
        }

        return View(upload);
    }

NOTE: you’ll probably want to do more than blindly save the file to an uploads directory, but that’s an exercise left for you. I had to save a set of files to the database. All you have to do is add more HttpPostedFile properties to your model. To my knowledge only the [Required] validation attribute can be used with file properties. The important thing is that the validation does work, and the JavaScript validations work.

Asp.Net MVC is shaping up to be a pretty good framework. I’d like to see a little more syntactic sugar for generating the file input control, but the fact that you can map it to a model at all is really cool. Just make sure the form control’s name matches the model’s property and you are set.


Viewing all articles
Browse latest Browse all 9364

Trending Articles