title: Model Binding for multipart/form-data (File + JSON) post in ASP.NET Core 1.1
body: <p>I'm attempting to build an ASP.NET Core 1.1 Controller method to handle an HTTP Request that looks like the following:</p>
  
  <pre><code>POST https://localhost/api/data/upload HTTP/1.1
  Content-Type: multipart/form-data; boundary=--------------------------625450203542273177701444
  Host: localhost
  Content-Length: 474
  
  ----------------------------625450203542273177701444
  Content-Disposition: form-data; name="file"; filename="myfile.txt"
  Content-Type: text/plain
  
  &lt;&lt; Contents of my file &gt;&gt;
  
  ----------------------------625450203542273177701444
  Content-Disposition: form-data; name="text"
  Content-Type: application/json
  
  {"md5":"595f44fec1e92a71d3e9e77456ba80d0","sessionIds":["123","abc"]}
  ----------------------------625450203542273177701444--
  </code></pre>
  
  <p>It's a <code>multipart/form-data</code> request with one part being a (small) file and the other part a json blob that is based on a provided specification.</p>
  
  <p>Ideally, I'd love my controller method to look like: </p>
  
  <pre class="lang-csharp prettyprint-override"><code>[HttpPost]
  public async Task Post(UploadPayload payload)
  {
     // TODO
  }
  
  public class UploadPayload
  {
      public IFormFile File { get; set; }
  
      [Required]
      [StringLength(32)]
      public string Md5 { get; set; }
  
      public List&lt;string&gt; SessionIds { get; set; }
  }
  </code></pre>
  
  <p>But alas, that doesn't Just Work {TM}.  When I have it like this, the <code>IFormFile</code> <em>does</em> get populated, but the json string doesn't get deserialized to the other properties.</p>
  
  <p>I've also tried adding a <code>Text</code> property to <code>UploadPayload</code> that has all the properties other than the <code>IFormFile</code> and that also doesn't receive the data.  E.g.</p>
  
  <pre class="lang-csharp prettyprint-override"><code>public class UploadPayload
  {
      public IFormFile File { get; set; }
  
      public UploadPayloadMetadata Text { get; set; }
  }
  
  public class UploadPayloadMetadata
  {
      [Required]
      [StringLength(32)]
      public string Md5 { get; set; }
  
      public List&lt;string&gt; SessionIds { get; set; }
  }
  </code></pre>
  
  <p>A workaround that I have is to avoid model binding and use <code>MultipartReader</code> along the lines of:</p>
  
  <pre class="lang-csharp prettyprint-override"><code>[HttpPost]
  public async Task Post()
  {
     ...
  
     var reader = new MultipartReader(Request.GetMultipartBoundary(), HttpContext.Request.Body);
  
     var section = await reader.ReadNextSectionAsync();
     var filePart = section.AsFileSection();
  
     // Do stuff &amp; things with the file
  
     section = await reader.ReadNextSectionAsync();
     var jsonPart = section.AsFormDataSection();
     var jsonString = await jsonPart.GetValueAsync();
  
     // Use $JsonLibrary to manually deserailize into the model
     // Do stuff &amp; things with the metadata
  
     ...
  }
  </code></pre>
  
  <p>Doing the above bypasses model validation features, etc.  Also, I thought maybe I could take that <code>jsonString</code> and then somehow get it into a state that I could then call <code>await TryUpdateModelAsync(payloadModel, ...)</code> but couldn't figure out how to get there either - and that didn't seem all that clean either.</p>
  
  <p>Is it possible to get to my desired state of "transparent" model binding like my first attempt?  If so, how would one get to that?</p>