ASP.NET MVC опубликовала привязку файловой модели, когда параметр Model

Есть ли способ получить размещенные файлы ( ), чтобы принять участие в привязке модели в ASP.NET MVC без ручного поиска контекста запроса в настраиваемом связующем устройстве и без создания отдельного метода действий который берет только опубликованный файл в качестве входных данных?

Я бы подумал, что это сработает:

 class MyModel { public HttpPostedFileBase MyFile { get; set; } public int? OtherProperty { get; set; } } 
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 , нет необходимости в каких-либо настраиваемых материалах.

    Другой способ – добавить скрытое поле с тем же именем, что и вход:

      

    Затем 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(); 

    и сообщения с формой, которая выглядит так:

     
    Choose file:

    Весь код скопирован прямо из сообщения блога …

    Вам не нужно регистрировать настраиваемое связующее, HttpPostedFileBase регистрируется по умолчанию в рамках:

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

    Это помогает читать книгу каждый раз за некоторое время, вместо того, чтобы полагаться исключительно на блоги и веб-форумы.

    Давайте будем гением компьютера.