当参数是Model时,ASP.NET MVC发布了文件模型绑定

时间:2009-06-06 22:19:27

标签: asp.net-mvc modelbinders defaultmodelbinder httppostedfilebase

有没有办法让发布的文件(<input type="file" />)参与ASP.NET MVC 中的模型绑定,而无需在自定义模型绑定器中手动查看请求上下文,也无需单独创建仅将已过帐文件作为输入的操作方法?

我原以为这会起作用:

class MyModel {
  public HttpPostedFileBase MyFile { get; set; }
  public int? OtherProperty { get; set; }
}

<form enctype="multipart/form-data">
  <input type="file" name="MyFile" />
  <input type="text" name="OtherProperty" />
</form>

public ActionResult Create(MyModel myModel) { ... } 

但鉴于上述情况, MyFile甚至不是绑定上下文中值提供者值的一部分。OtherProperty当然是。)但它如果我这样做的话会有效:

public ActionResult Create(HttpPostedFileBase postedFile, ...) { ... } 

那么,为什么当参数是模型时不会发生绑定,我怎样才能使它工作?我使用自定义模型绑定器没有问题,但是如何在不查看Request.Files["MyFile"]的情况下在自定义模型绑定器中执行此操作?

为了保持一致性,清晰度和可测试性,我希望我的代码能够自动绑定模型上的所有属性,包括绑定到已发布文件的属性,而无需手动检查请求上下文。我目前正在使用the approach Scott Hanselman wrote about测试模型绑定。

或者我是以错误的方式解决这个问题?你怎么解决这个问题?或者,由于Request.Form和Request.Files之间的分离历史,这是不可能的设计?

4 个答案:

答案 0 :(得分:30)

原因是ValueProviderDictionary仅在Request.FormRouteDataRequest.QueryString中查找以填充模型绑定上下文中的值提供程序字典。因此,自定义模型绑定器无法允许已发布的文件参与模型绑定,而无需直接检查请求上下文中的文件集合。这是我发现完成同样事情的最接近的方式:

public ActionResult Create(MyModel myModel, HttpPostedFileBase myModelFile) { }

只要myModelFile实际上是file输入表单字段的名称,就不需要任何自定义内容。

答案 1 :(得分:14)

另一种方法是添加一个与输入名称相同的隐藏字段:

<input type="hidden" name="MyFile" id="MyFileSubmitPlaceHolder" />

然后DefaultModelBinder将看到一个字段并创建正确的活页夹。

答案 2 :(得分:6)

您是否看过this postthe one you linked to(通过another one ...)链接到的{{3}}?

如果没有,看起来很简单。这是他使用的模型绑定器:

public class HttpPostedFileBaseModelBinder : IModelBinder {
    public ModelBinderResult BindModel(ModelBindingContext bindingContext) {
        HttpPostedFileBase theFile =
            bindingContext.HttpContext.Request.Files[bindingContext.ModelName];
        return new ModelBinderResult(theFile);
    }
}

他在Global.asax.cs注册如下:

ModelBinders.Binders[typeof(HttpPostedFileBase)] = 
    new HttpPostedFileBaseModelBinder();

以及带有如下形式的帖子:

<form action="/File/UploadAFile" enctype="multipart/form-data" method="post">
    Choose file: <input type="file" name="theFile" />
    <input type="submit" />
</form>

所有代码都直接从博客文章中复制......

答案 3 :(得分:-16)

您无需注册自定义活页夹,默认情况下会在框架中注册HttpPostedFileBase

public ActionResult Create(HttpPostedFileBase myFile)
{
    ...
}

每隔一段时间就有read a book次帮助,而不是仅依靠博客和网络论坛。