Carl Hörberg
Carl Hörberg

Reputation: 6005

Can't get HttpPostedFileBase to bind correctly in Asp.Net MVC 1.0

I can't have asp.net mvc 1.0 to bind HttpPostedFileBase for me.

this is my EditModel class.

public class PageFileEditModel
{
    public HttpPostedFileBase File { get; set; }
    public string Category { get; set; }
}

and this is my edit method header.

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(int id, FormCollection formCollection, PageFileEditModel[] pageFiles)

and this is my HTML

<input type="file" name="pageFiles[0].File" />
<input type="text" name="pageFiles[0].Category" />
<input type="file" name="pageFiles[1].File" />
<input type="text" name="pageFiles[1].Category" />

Category is bind correctly, but File is always null.

I've verifed that the files indeed are in Request.Files.

The HttpPostedFileBaseModelBinder is added by default so can't figure out what is going wrong..

Upvotes: 1

Views: 1568

Answers (2)

Levi
Levi

Reputation: 32828

There's a bug in MVC 1 (fixed in MVC 2 RC) where HttpPostedFileBase objects aren't bound if they're properties on your model type rather than parameters to your action method. Workaround for MVC 1:

<input type="file" name="theFile[0]" />
<input type="hidden" name="theFile[0].exists" value="true" />
<input type="file" name="theFile[1]" />
<input type="hidden" name="theFile[1].exists" value="true" />

That is, for each file upload element foo have a foo.exists hidden input element. This will cause the DefaultModelBinder's short-circuiting logic not to kick in and it should correctly bind the HPFB property.

Upvotes: 1

takepara
takepara

Reputation: 10433

This is a specification.

Scott Hanselman's Computer Zen - ASP.NET MVC Beta released - Coolness Ensues

This is V1 RTW base model binder sample code.

1.Make custom model binder.

using System.Web.Mvc;

namespace Web
{
  public class HttpPostedFileBaseModelBinder : IModelBinder
  {
    public object BindModel(ControllerContext controllerContext, 
                            ModelBindingContext bindingContext)
    {
      var bind = new PostedFileModel();
      var bindKey = (string.IsNullOrEmpty(bindingContext.ModelName) ?
        "" : bindingContext.ModelName + ".") + "PostedFile";
      bind.PostedFile = controllerContext.HttpContext.Request.Files[bindKey];

      return bind;
    }
  }
}

2.Create model class.

using System.Web;

namespace Web
{
  public class PostedFileModel
  {
    public HttpPostedFileBase PostedFile { get; set; }
  }
}

3.Entry model binder in global.asax.cs.

protected void Application_Start()
{
  RegisterRoutes(RouteTable.Routes);
  ModelBinders.Binders[typeof(PostedFileModel)] = 
                 new HttpPostedFileBaseModelBinder();
}

Upvotes: 1

Related Questions