LCOV - code coverage report
Current view: top level - Cqrs.WebApi/Formatters/FormMultipart/Converters - ObjectToMultipartDataByteArrayConverter.cs Hit Total Coverage
Test: doc-coverage.info Lines: 0 3 0.0 %
Date: 2017-07-26

          Line data    Source code
       1             : using System;
       2             : using System.Collections;
       3             : using System.Collections.Generic;
       4             : using System.Linq;
       5             : using System.Runtime.Serialization;
       6             : using System.Text;
       7             : using Cqrs.WebApi.Formatters.FormMultipart.Infrastructure;
       8             : using Cqrs.WebApi.Formatters.FormMultipart.Infrastructure.Extensions;
       9             : 
      10             : namespace Cqrs.WebApi.Formatters.FormMultipart.Converters
      11             : {
      12             :         public class ObjectToMultipartDataByteArrayConverter
      13           0 :         {
      14             :                 private MultipartFormatterSettings Settings { get; set; }
      15             : 
      16           0 :                 public ObjectToMultipartDataByteArrayConverter(MultipartFormatterSettings settings)
      17             :                 {
      18             :                         if (settings == null)
      19             :                                 throw new ArgumentNullException("settings");
      20             : 
      21             :                         Settings = settings;
      22             :                 }
      23             : 
      24           0 :                 public byte[] Convert(object value, string boundary)
      25             :                 {
      26             :                         if(value == null)
      27             :                                 throw new ArgumentNullException("value");
      28             :                         if (String.IsNullOrWhiteSpace(boundary))
      29             :                                 throw new ArgumentNullException("boundary");
      30             : 
      31             :                         List<KeyValuePair<string, object>> propertiesList = ConvertObjectToFlatPropertiesList(value);
      32             : 
      33             :                         byte[] buffer = GetMultipartFormDataBytes(propertiesList, boundary);
      34             :                         return buffer;
      35             :                 }
      36             : 
      37             :                 private List<KeyValuePair<string, object>> ConvertObjectToFlatPropertiesList(object value)
      38             :                 {
      39             :                         var propertiesList = new List<KeyValuePair<string, object>>();
      40             :                         if (value is FormData)
      41             :                         {
      42             :                                 FillFlatPropertiesListFromFormData((FormData) value, propertiesList);
      43             :                         }
      44             :                         else
      45             :                         {
      46             :                                 FillFlatPropertiesListFromObject(value, "", propertiesList);   
      47             :                         }
      48             : 
      49             :                         return propertiesList;
      50             :                 }
      51             : 
      52             :                 private void FillFlatPropertiesListFromFormData(FormData formData, List<KeyValuePair<string, object>> propertiesList)
      53             :                 {
      54             :                         foreach (var field in formData.Fields)
      55             :                         {
      56             :                                 propertiesList.Add(new KeyValuePair<string, object>(field.Name, field.Value));
      57             :                         }
      58             :                         foreach (var field in formData.Files)
      59             :                         {
      60             :                                 propertiesList.Add(new KeyValuePair<string, object>(field.Name, field.Value));
      61             :                         }
      62             :                 }
      63             : 
      64             :                 private void FillFlatPropertiesListFromObject(object obj, string prefix, List<KeyValuePair<string, object>> propertiesList)
      65             :                 {
      66             :                         if (obj != null)
      67             :                         {
      68             :                                 Type type = obj.GetType();
      69             : 
      70             :                                 if (obj is IDictionary)
      71             :                                 {
      72             :                                         var dict = obj as IDictionary;
      73             :                                         int index = 0;
      74             :                                         foreach (var key in dict.Keys)
      75             :                                         {
      76             :                                                 string indexedKeyPropName = String.Format("{0}[{1}].Key", prefix, index);
      77             :                                                 FillFlatPropertiesListFromObject(key, indexedKeyPropName, propertiesList);
      78             : 
      79             :                                                 string indexedValuePropName = String.Format("{0}[{1}].Value", prefix, index);
      80             :                                                 FillFlatPropertiesListFromObject(dict[key], indexedValuePropName, propertiesList);
      81             : 
      82             :                                                 index++;
      83             :                                         }
      84             :                                 }
      85             :                                 else if (obj is ICollection && !IsByteArrayConvertableToHttpFile(obj))
      86             :                                 {
      87             :                                         var list = obj as ICollection;
      88             :                                         int index = 0;
      89             :                                         foreach (var indexedPropValue in list)
      90             :                                         {
      91             :                                                 string indexedPropName = String.Format("{0}[{1}]", prefix, index);
      92             :                                                 FillFlatPropertiesListFromObject(indexedPropValue, indexedPropName, propertiesList);
      93             : 
      94             :                                                 index++;
      95             :                                         }
      96             :                                 }
      97             :                                 else if (type.IsCustomNonEnumerableType())
      98             :                                 {
      99             :                                         foreach (var propertyInfo in type.GetProperties())
     100             :                                         {
     101             :                                                 if (propertyInfo.CustomAttributes.Any(attribute => attribute.AttributeType == typeof(IgnoreDataMemberAttribute)))
     102             :                                                         continue;
     103             :                                                 string propName = string.IsNullOrWhiteSpace(prefix)
     104             :                                                         ? propertyInfo.Name
     105             :                                                         : String.Format("{0}.{1}", prefix, propertyInfo.Name);
     106             :                                                 object propValue = propertyInfo.GetValue(obj);
     107             : 
     108             :                                                 FillFlatPropertiesListFromObject(propValue, propName, propertiesList);
     109             :                                         }
     110             :                                 }
     111             :                                 else
     112             :                                 {
     113             :                                         propertiesList.Add(new KeyValuePair<string, object>(prefix, obj));
     114             :                                 }
     115             :                         }
     116             :                 }
     117             : 
     118             :                 private byte[] GetMultipartFormDataBytes(List<KeyValuePair<string, object>> postParameters, string boundary)
     119             :                 {
     120             :                         if (postParameters == null || !postParameters.Any())
     121             :                                 throw new Exception("Cannot convert data to multipart/form-data format. No data found.");
     122             : 
     123             :                         Encoding encoding = Encoding.UTF8;
     124             : 
     125             :                         using (var formDataStream = new System.IO.MemoryStream())
     126             :                         {
     127             :                                 bool needsClrf = false;
     128             : 
     129             :                                 foreach (var param in postParameters)
     130             :                                 {
     131             :                                         // Add a CRLF to allow multiple parameters to be added.
     132             :                                         // Skip it on the first parameter, add it to subsequent parameters.
     133             :                                         if (needsClrf)
     134             :                                                 formDataStream.Write(encoding.GetBytes("\r\n"), 0, encoding.GetByteCount("\r\n"));
     135             : 
     136             :                                         needsClrf = true;
     137             : 
     138             :                                         if (param.Value is HttpFile || IsByteArrayConvertableToHttpFile(param.Value))
     139             :                                         {
     140             :                                                 HttpFile httpFileToUpload = param.Value is HttpFile
     141             :                                                         ? (HttpFile) param.Value
     142             :                                                         : new HttpFile(null, null, (byte[]) param.Value);
     143             : 
     144             :                                                 // Add just the first part of this param, since we will write the file data directly to the Stream
     145             :                                                 string header = string.Format
     146             :                                                 (
     147             :                                                         "--{0}\r\nContent-Disposition: form-data; name=\"{1}\"; filename=\"{2}\"\r\nContent-Type: {3}\r\n\r\n",
     148             :                                                         boundary,
     149             :                                                         param.Key,
     150             :                                                         httpFileToUpload.FileName ?? param.Key,
     151             :                                                         httpFileToUpload.MediaType ?? "application/octet-stream"
     152             :                                                 );
     153             : 
     154             :                                                 formDataStream.Write(encoding.GetBytes(header), 0, encoding.GetByteCount(header));
     155             : 
     156             :                                                 // Write the file data directly to the Stream, rather than serializing it to a string.
     157             :                                                 formDataStream.Write(httpFileToUpload.Buffer, 0, httpFileToUpload.Buffer.Length);
     158             :                                         }
     159             :                                         else
     160             :                                         {
     161             :                                                 string objString = "";
     162             :                                                 if (param.Value != null)
     163             :                                                 {
     164             :                                                         var typeConverter = param.Value.GetType().GetToStringConverter();
     165             :                                                         if (typeConverter != null)
     166             :                                                         {
     167             :                                                                 objString = typeConverter.ConvertToString(null, Settings.CultureInfo, param.Value);
     168             :                                                         }
     169             :                                                         else
     170             :                                                         {
     171             :                                                                 throw new Exception(String.Format("Type \"{0}\" cannot be converted to string", param.Value.GetType().FullName));
     172             :                                                         }
     173             :                                                 }
     174             : 
     175             :                                                 string postData = string.Format
     176             :                                                 (
     177             :                                                         "--{0}\r\nContent-Disposition: form-data; name=\"{1}\"\r\n\r\n{2}",
     178             :                                                         boundary,
     179             :                                                         param.Key,
     180             :                                                         objString
     181             :                                                 );
     182             :                                                 formDataStream.Write(encoding.GetBytes(postData), 0, encoding.GetByteCount(postData));
     183             :                                         }
     184             :                                 }
     185             : 
     186             :                                 // Add the end of the request.  Start with a newline
     187             :                                 string footer = "\r\n--" + boundary + "--\r\n";
     188             :                                 formDataStream.Write(encoding.GetBytes(footer), 0, encoding.GetByteCount(footer));
     189             : 
     190             :                                 byte[] formData = formDataStream.ToArray();
     191             : 
     192             :                                 return formData;
     193             :                         }
     194             :                 }
     195             : 
     196             :                 private bool IsByteArrayConvertableToHttpFile(object value)
     197             :                 {
     198             :                         return value is byte[] && Settings.SerializeByteArrayAsHttpFile;
     199             :                 }
     200             :         }
     201             : }

Generated by: LCOV version 1.10