有没有办法让发布的文件(<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之间的分离历史,这是不可能的设计?
答案 0 :(得分:30)
原因是ValueProviderDictionary
仅在Request.Form
,RouteData
和Request.QueryString
中查找以填充模型绑定上下文中的值提供程序字典。因此,自定义模型绑定器无法允许已发布的文件参与模型绑定,而无需直接检查请求上下文中的文件集合。这是我发现完成同样事情的最接近的方式:
public ActionResult Create(MyModel myModel, HttpPostedFileBase myModelFile) { }
只要myModelFile
实际上是file
输入表单字段的名称,就不需要任何自定义内容。
答案 1 :(得分:14)
另一种方法是添加一个与输入名称相同的隐藏字段:
<input type="hidden" name="MyFile" id="MyFileSubmitPlaceHolder" />
然后DefaultModelBinder将看到一个字段并创建正确的活页夹。
答案 2 :(得分:6)
您是否看过this post从the 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次帮助,而不是仅依靠博客和网络论坛。