ASP.NET MVC публикует привязку файловой модели, когда параметром является Model - PullRequest
24 голосов
/ 07 июня 2009

Есть ли способ получить опубликованные файлы (<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"]?

Для согласованности, ясности и тестируемости я хотел бы, чтобы мой код обеспечивал автоматическое связывание всех свойств модели, в том числе привязанных к опубликованным файлам, без ручной проверки контекста запроса. В настоящее время я тестирую привязку модели, используя подход, который Скотт Хансельман написал о .

Или я поступаю неправильно? Как бы вы решили это? Или это не возможно по замыслу из-за истории разделения между Request.Form и Request.Files?

Ответы [ 4 ]

30 голосов
/ 09 июня 2009

Оказывается, причина в том, что ValueProviderDictionary ищет только в Request.Form, RouteData и Request.QueryString для заполнения словаря поставщиков значений в контексте привязки модели. Таким образом, пользовательский механизм связывания не может позволить размещенным файлам участвовать в связывании модели, не проверяя коллекцию файлов непосредственно в контексте запроса. Это самый близкий способ сделать то же самое:

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

Поскольку myModelFile фактически является именем поля формы ввода file, никаких дополнительных настроек не требуется.

14 голосов
/ 30 октября 2009

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

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

DefaultModelBinder увидит поле и создаст правильное связующее.

6 голосов
/ 07 июня 2009

Вы смотрели на этот пост , на который он ссылается с на тот, на который вы ссылались (через еще один ...)?

Если нет, то выглядит довольно просто. Это модель связующего он использует:

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>

Весь код скопирован прямо с поста блога ...

0 голосов
/ 07 июня 2009

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

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

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *,, "" * "-" * "
...