24

게시 된 파일 (<input type="file" />)을 ASP.NET MVC 의 모델 바인딩에 참여 시키려면 사용자 지정 모델 바인더의 요청 컨텍스트를 수동으로 보지 않아도됩니다 게시 된 파일 만 입력으로 사용하는 별도의 작업 방법을 만들지 않고?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의 분리 이력 때문에 설계 상으로는 가능하지 않습니까?

답변

29

그것은 이유는 ValueProviderDictionary는 모델 바인딩 컨텍스트에서 값 공급자 사전을 채울 Request.Form, RouteDataRequest.QueryString에 보이는 것입니다 밝혀졌습니다. 따라서 사용자 정의 모델 바인더가 게시 된 파일을 요청 컨텍스트에서 파일 컬렉션을 직접 검사하지 않고 모델 바인딩에 참여할 수있는 방법은 없습니다.만큼 myModelFile 실제로 file 입력 양식 필드의 이름으로

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

, 사용자 지정 물건에 대한 필요가 없습니다 : 이것은 내가 같은 일을 수행하기 위해 찾은 가장 가까운 방법입니다.

+5

* 참고 : * 양식의'enctype' 속성을 간과하지 마십시오. 그것은''multipart/form-data ''로 지정되어야합니다. 그렇지 않으면 입력 태그의'name' 속성과 일치하는 이름을 가진'HttpPostedFileBase' 인자는 POST에서'null'을 유지합니다. –

+0

동일한 사용했지만 오류가 있어요 : - 내 $ .ajax 설정 한 여러 매개 변수를 바인딩 할 수 없습니다 : - 형식 : 'POST', dataType : 'json', contentType : 'multipart/form-data' , 데이터 : formData – ujjaval

6

this post에서 그가 the one you linked to (another one ...을 통해)에 링크 된 것을 보았습니까?

그렇지 않은 경우 매우 간단 해 보입니다.

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

다음과 같이 그는 Global.asax.cs에 등록 :

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

모든 :이처럼 보이는 양식

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

및 게시물 이것은 그가 사용하는 모델 바인더입니다 코드가 블로그 게시물에서 바로 복사됩니다.

+0

사실, 현재 사용하고있는 방법입니다. 그러나이 방법에는 두 가지 문제가 있습니다. 1; 그것은 (bindContext.HttpContext.Request를 통해) 요청 문맥을 사용하는데, 나는 정말로 원하지 않는다. 그리고 2; 게시물이 업로드 된 파일로만 구성된 시나리오 만 처리합니다 (물론 쉽게 변경할 수 있습니다). – bzlm

+0

또한 BindModel (ModelBindingContext bindingContext)은 시험판 코드처럼 보입니다. 거기에 ControllerContext가 있습니다. – bzlm

+1

MVC Framework 소스 코드를 살펴 보셨습니까? "정상적인"모델 바인더가 어떻게 작동하는지 모르겠지만 HttpContext.Current.Request.Form [] 컬렉션 *을 사용하지 않고 양식 값을 가져올 수있는 방법을 실제로 볼 수는 없습니다 ... http://weblogs.asp.net/scottgu/archive/2008/03/21/asp-net-mvc-source-code-now-available.aspx –

-16

당신은 HttpPostedFileBase은 프레임 워크에 기본적으로 등록되어, 사용자 정의 바인더를 등록 할 필요가 없습니다

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

대신 블로그와 웹 포럼에 전적으로 의존, 한동안마다 read a book에 도움이됩니다.

+0

게시 된 파일을 유일한 매개 변수로 사용하는 작업 방법을 원하지 않는다는 사실에 대해보다 명확하게 질문을 편집했습니다. 게시 된 파일이 모델의 여러 속성 중 하나 일 뿐이라면 동일한 작업을 수행 할 수있는 방법이 있습니까? (나는 다른 ASP.NET MVC 책을 가지고 있습니다. :) – bzlm

+0

이것은 정답입니다. 나는 같은 문제를 가지고 있었다. HttpPostedFileBase는 바인딩하지만 HttpPostedFile은 바인딩하지 않습니다. –

+0

아니요, HttpPostedFileBase는 기본 모델 바인더에서 표준 값 공급자 바인딩을 사용하여 바인딩하지 않습니다. 그것은이 대답의 방법으로 묶을 것이다. – bzlm

14

또 다른 방법은 입력과 같은 이름이 숨겨진 필드를 추가하는 것이다

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

DefaultModelBinder 다음 필드를 확인하고 적절한 결합제를 생성한다.

+2

ASP.NET MVC 2 RC와 같이 숨겨진 필드가없는 것 같습니다. –

+0

절대적으로 정확한지, ASP.NET MVC 2를 사용하고 있으며 추가 작업을 수행하지 않고 내 파일 입력을 내 모델에 성공적으로 바인딩 할 수 있습니다. 환상적! – Pandincus