当参数为 Model 时 ASP.NET MVC 发布文件模型绑定
-
12-09-2019 - |
题
有什么办法可以获取发布的文件(<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"]
?
为了一致性、清晰度和可测试性,我希望我的代码能够自动绑定模型上的所有属性,包括那些绑定到已发布文件的属性,而无需手动检查请求上下文。我目前正在使用测试模型绑定 斯科特·汉塞尔曼(Scott Hanselman)所写的方法.
或者我以错误的方式处理这件事?你会如何解决这个问题?或者由于 Request.Form 和 Request.Files 之间的分离历史,这在设计上是不可能的吗?
解决方案
原来的原因在于,ValueProviderDictionary
只查找Request.Form
,RouteData
和Request.QueryString
填充模型中的绑定上下文值提供字典。因此,有没有办法让一个自定义的模型绑定,允许发布文件,参与模型,而无需在请求上下文中直接检查文件的集合结合。这是我发现来完成同样的事情最接近的方式:
public ActionResult Create(MyModel myModel, HttpPostedFileBase myModelFile) { }
只要myModelFile
实际上是file
输入表单字段的名称,没有必要对任何自定义的东西。
其他提示
另一种方法是添加一个隐藏字段具有相同的名称作为输入:
<input type="hidden" name="MyFile" id="MyFileSubmitPlaceHolder" />
在DefaultModelBinder然后将看到一个字段和创建正确的粘合剂。
你看过吗 这个帖子 他链接到的 您链接到的那个 (通过 另一个...)?
如果没有,看起来很简单。这是他使用的模型活页夹:
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>
所有代码都是直接从博客文章中复制的......
您并不需要注册一个定制绑定,HttpPostedFileBase
默认情况下,在框架中注册的:
public ActionResult Create(HttpPostedFileBase myFile)
{
...
}
它有助于而不是向看书每一次在一段时间,仅仅在博客和网络论坛依赖