1

這些鏈接沒有幫助我:如何爲ASP.NET 4.5的Web API創建MultipartFormFormatter

例子:

//Model: 
public class Group 
{ 
    public int Id { get; set; }   
    public File File { get; set; } 
} 

//Controller: 
[HttpPost] 
public void SaveGroup([FromBody]Group group) {} 

//Formatter: 
public class MultipartFormFormatter : MediaTypeFormatter 
{ 
    private const string StringMultipartMediaType = "multipart/form-data"; 

    public MultipartFormFormatter() 
    { 
     this.SupportedMediaTypes.Add(new MediaTypeHeaderValue(StringMultipartMediaType)); 

    } 

    public override bool CanReadType(Type type) 
    { 
     return true; 
    } 

    public override bool CanWriteType(Type type) 
    { 
     return false; 
    } 

    public async override Task<object> ReadFromStreamAsync(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger) 
    { 
     //Implementation? What here should be? 
    }  
} 

應該是什麼方法ReadFromStreamAsync返回?

我該如何製作這樣才能正確傳輸參數到動作中?

回答

5
public class MultipartFormFormatter : FormUrlEncodedMediaTypeFormatter 
{ 
    private const string StringMultipartMediaType = "multipart/form-data"; 
    private const string StringApplicationMediaType = "application/octet-stream"; 

    public MultipartFormFormatter() 
    { 
     this.SupportedMediaTypes.Add(new MediaTypeHeaderValue(StringMultipartMediaType)); 
     this.SupportedMediaTypes.Add(new MediaTypeHeaderValue(StringApplicationMediaType)); 
    } 

    public override bool CanReadType(Type type) 
    { 
     return true; 
    } 

    public override bool CanWriteType(Type type) 
    { 
     return false; 
    } 

    public override async Task<object> ReadFromStreamAsync(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger) 
    { 
     var parts = await content.ReadAsMultipartAsync(); 
     var obj = Activator.CreateInstance(type); 
     var propertiesFromObj = obj.GetType().GetRuntimeProperties().ToList(); 

     foreach (var property in propertiesFromObj.Where(x => x.PropertyType == typeof(FileModel))) 
     { 
      var file = parts.Contents.FirstOrDefault(x => x.Headers.ContentDisposition.Name.Contains(property.Name)); 

      if (file == null || file.Headers.ContentLength <= 0) continue; 

      try 
      { 
       var fileModel = new FileModel(file.Headers.ContentDisposition.FileName, Convert.ToInt32(file.Headers.ContentLength), ReadFully(file.ReadAsStreamAsync().Result)); 
       property.SetValue(obj, fileModel); 
      } 
      catch (Exception e) 
      { 
      } 
     } 

     foreach (var property in propertiesFromObj.Where(x => x.PropertyType != typeof(FileModel))) 
     { 
      var formData = parts.Contents.FirstOrDefault(x => x.Headers.ContentDisposition.Name.Contains(property.Name)); 

      if (formData == null) continue; 

      try 
      { 
       var strValue = formData.ReadAsStringAsync().Result; 
       var valueType = Nullable.GetUnderlyingType(property.PropertyType) ?? property.PropertyType; 
       var value = Convert.ChangeType(strValue, valueType); 
       property.SetValue(obj, value); 
      } 
      catch (Exception e) 
      { 
      } 
     } 

     return obj; 
    } 

    private byte[] ReadFully(Stream input) 
    { 
     var buffer = new byte[16 * 1024]; 
     using (var ms = new MemoryStream()) 
     { 
      int read; 
      while ((read = input.Read(buffer, 0, buffer.Length)) > 0) 
      { 
       ms.Write(buffer, 0, read); 
      } 
      return ms.ToArray(); 
     } 
    } 
} 

public class FileModel 
{ 
    public FileModel(string filename, int contentLength, byte[] content) 
    { 
     Filename = filename; 
     ContentLength = contentLength; 
     Content = content; 
    } 

    public string Filename { get; set; } 

    public int ContentLength { get; set; } 

    public byte[] Content { get; set; } 

} 
+0

感謝您的支持!幫我掐了一下。我添加了'FileModel'類def來完全複製/粘貼。要使用:在控制器動作的參數中爲模型添加一個'FileModel'屬性,並且不要忘記在引導中執行'GlobalConfiguration.Configuration.Formatters.Add(new MultipartFormFormatter());'。 – jkoreska