title: Upload file through c# using JSON request and RestSharp
body: <p>After managing to load data to my Rails Server through c# (check <a href="https://stackoverflow.com/questions/14141174/c-sharp-adding-double-quotes-to-start-and-end-of-json-string-results-in-server-d">here</a> to know what i am talking about), i am now trying to upload a file to that same server, along with other data.</p>
  
  <p>In Ruby, I am able to do this with the code :</p>
  
  <pre><code>require 'HTTMultiParty'
  
      class ReceiptCreate
          include HTTMultiParty
          # Log to file
          # debug_output File.new("httparty1.log", "w+")
          base_uri "localhost:3000"
          format :json
          headers "Accept" =&gt; "application/json"
  
        def initialize
        end
  
        def post(machine_serial,filepath,tag_number,token)
          options = { body: 
                      {receipt:
                          {tag_number:tag_number,
                           receipt_file: File.new(filepath),
                           ispaperduplicate:0
                           },
                      machine:
                          {serial_number: machine_serial,
                           safe_token: token
                           }
                      }               
                  }
          self.class.post('/receipts', options)
        end
      end
  
  receipt = ReceiptCreate.new()
  filename1 = "C:\\filename1.pdf"
  filename2 = "C:\\filename2.pdf"
  response=receipt.post("2803433",filename2,"p94tt7w","123")
  puts response
  </code></pre>
  
  <p>an when I inspect the parameters on the rails server i see</p>
  
  <pre><code>Parameters: {"receipt"=&gt;{"tag_number"=&gt;"p94tt7w", "receipt_file"=&gt;#&lt;ActionDispatch::Http::UploadedFile:0x4183ea8 @original_filename="Invoice.pdf", @content_type="application/octet-stream", @headers="Content-Disposition: form-data; name=\"receipt[receipt_file]\"; filename=\"Invoice.pdf\"\r\nContent-Length: 11653\r\nContent-Type: application/octet-stream\r\nContent-Transfer-Encoding: binary\r\n", @tempfile=#&lt;File:C:/Users/diogo/AppData/Local/Temp/RackMultipart20130103-18168-efiqia&gt;&gt;, "ispaperduplicate"=&gt;"0"}, "machine"=&gt;{"serial_number"=&gt;"2803433", "safe_token"=&gt;"123"}}
  </code></pre>
  
  <p>But if i try to do the same with my c# code below</p>
  
  <pre><code>using System;
  using System.Collections.Generic;
  using System.ComponentModel;
  using System.Data;
  using System.Drawing;
  using System.Linq;
  using System.Text;
  using System.Windows.Forms;
  using RestSharp;
  using System.Web.Script.Serialization;
  using System.IO;
  
  namespace RonRestClient
  {
  
  
      class templateRequest
      {
          public Receipt receipt;
          public class Receipt
          {
              public float total;
              public String tag_number;
              public bool ispaperduplicate = true;
              public byte[] receipt_file;
              public Receipt(float total, String tagnr, string filepath)
              {
                  this.total = total;
                  this.tag_number = tagnr;
                  this.receipt_file = File.ReadAllBytes(filepath);
              }
          };
          public Machine machine;
          public class Machine
          {
              public String serial_number;
              public String safe_token;
              public Machine(String machinenr, String safe_token)
              {
                  this.serial_number = machinenr;
                  this.safe_token = safe_token;
              }
          };
      }
  
  
      public partial class Form1 : Form
      {
          public Form1()
          {
              InitializeComponent();
          }
  
          private void button1_Click(object sender, EventArgs e)
          {
  
              string path = @"C:\filename2.pdf";
              string tagnr = "p94tt7w";
              string machinenr = "2803433";
              string safe_token = "123";
              float total = 100;
  
              templateRequest req = new templateRequest();
              req.receipt = new templateRequest.Receipt(total, tagnr, path);
              req.machine = new templateRequest.Machine(machinenr, safe_token);
              //string json_body = JsonConvert.SerializeObject(req);
              //string json_body = new JavaScriptSerializer().Serialize(req);
  
  
              //var json_body = "{\"receipt\" : {\"total\":"+total+", \"tag_number\":\""+tagnr+"\",\"ispaperduplicate\":true},\"machine\":{\"serial_number\": \""+machinenr+"\",\"safe_token\": \""+safe_token+"\"}}";
  
              var client = new RestClient("http://localhost:3000/receipts");
  
              var request = new RestRequest(Method.POST);
  
  
              //set request Body
              request.AddHeader("Content-type", "application/json");
              request.AddHeader("Accept", "application/json");
              request.RequestFormat = DataFormat.Json;
  
              request.AddBody(req); 
              //request.AddParameter("application/json", json_body, ParameterType.RequestBody);
  
              // easily add HTTP Headers
  
  
              // add files to upload (works with compatible verbs)
              //request.AddFile("receipt/receipt_file",path);
  
              // execute the request
  
              IRestResponse response = client.Execute(request);
              var content = response.Content; // raw content as string
              if(response.ErrorMessage !="") content += response.ErrorMessage;
              response_box.Text = content;
  
  
  
  
          }
      }
  }
  </code></pre>
  
  <p>I get this </p>
  
  <pre><code>Parameters: {"receipt"=&gt;{"total"=&gt;100, "tag_number"=&gt;"p94tt7w", "ispaperduplicate"=&gt;true, "receipt_file"=&gt;[37, 80, [n3...nX], 10]}, "machine"=&gt;{"serial_number"=&gt;"2803433", "safe_token"=&gt;"123"}}
  </code></pre>
  
  <p>This seems to mean basically that Restsharp just thinks that my file is just another field.</p>
  
  <p>RestSharp seems to have a method to add files <code>request.AddFile("receipt/receipt_file",path);</code>, and i believe that this should probably be the way to go...but when i just try and add the file, i get an error message saying :</p>
  
  <blockquote>
    <p>This property cannot be set after writing has started.</p>
  </blockquote>
  
  <p>Do I need to set each attribute of the file separately?</p>
  
  <p><strong>EDIT</strong></p>
  
  <p>Meanwhile i found this <a href="http://nediml.wordpress.com/2012/05/10/uploading-files-to-remote-server-with-multiple-parameters/" rel="nofollow noreferrer">post</a>, changed my code to :</p>
  
  <pre><code>using System;
  using System.Collections.Generic;
  using System.ComponentModel;
  using System.Data;
  using System.Drawing;
  using System.Linq;
  using System.Text;
  using System.Windows.Forms;
  using RestSharp;
  using System.Web.Script.Serialization;
  using System.IO;
  using System.Net;
  
  namespace RonRestClient
  {
  
  
      class templateRequest
      {
          public Receipt receipt;
          public class Receipt
          {
              //public float total;
              public String tag_number;
              public bool ispaperduplicate = true;
              //public byte[] receipt_file;
              public Receipt(String tagnr)
              {
                  //this.total = total;
                  this.tag_number = tagnr;
                 // this.receipt_file = File.ReadAllBytes(filepath);
              }
          };
          public Machine machine;
          public class Machine
          {
              public String serial_number;
              public String safe_token;
              public Machine(String machinenr, String safe_token)
              {
                  this.serial_number = machinenr;
                  this.safe_token = safe_token;
              }
          };
      }
  
  
      public partial class Form1 : Form
      {
          public Form1()
          {
              InitializeComponent();
          }
  
          private void button1_Click(object sender, EventArgs e)
          {
  
              string path = @"C:\filename2.pdf";
              string tagnr = "p94tt7w";
              string machinenr = "2803433";
              string safe_token = "123";
              float total = 100;
  
              templateRequest req = new templateRequest();
              req.receipt = new templateRequest.Receipt(tagnr);
              req.machine = new templateRequest.Machine(machinenr, safe_token);
  
              var request = new RestRequest("/receipts",Method.POST);
              request.AddParameter("receipt[total]", total);
              request.AddParameter("receipt[tag_number]", tagnr);
              request.AddParameter("machine[serial_number]", machinenr);
              request.AddParameter("machine[safe_token]", safe_token);
              request.AddFile("receipt[receipt_file]", File.ReadAllBytes(path), "Invoice.pdf", "application/octet-stream");
  
              // Add HTTP Headers
              request.AddHeader("Content-type", "application/json");
              request.AddHeader("Accept", "application/json");
              request.RequestFormat = DataFormat.Json;
              //set request Body
              //request.AddBody(req); 
  
  
              // execute the request
              //calling server with restClient
              RestClient restClient = new RestClient("http://localhost:3000");
              restClient.ExecuteAsync(request, (response) =&gt;
              {
  
                  if (response.StatusCode == HttpStatusCode.OK)
                  {
                      //upload successfull
                      MessageBox.Show("Upload completed succesfully...\n" + response.Content);
                  }
                  else
                  {
                      //error ocured during upload
                      MessageBox.Show(response.StatusCode + "\n" + response.StatusDescription);
                  }
              });
  
          }
  
      }
  
  }
  </code></pre>
  
  <p>and now am getting the parameters :</p>
  
  <pre><code>Parameters: {"receipt"=&gt;{"total"=&gt;"100", "tag_number"=&gt;"p94tt7w", "receipt_file"=&gt;#&lt;ActionDispatch::Http::UploadedFile:0x3db42d8 @original_filename="Invoice.pdf", @content_type="application/octet-stream", @headers="Content-Disposition: form-data; name=\"receipt[receipt_file]\"; filename=\"Invoice.pdf\"\r\nContent-Type: application/octet-stream\r\n", @tempfile=#&lt;File:C:/Users/diogo/AppData/Local/Temp/RackMultipart20130103-18168-9mbt3h&gt;&gt;}, "machine"=&gt;{"serial_number"=&gt;"2803433", "safe_token"=&gt;"123"}}
  </code></pre>
  
  <p>Along with an HTTP 422 - Unprocessable Entity error.</p>
  
  <p>If I am to compare these parameters with the ones that i have working from the ruby code, now the only difference seems to be that this last message does not have the Content-length and Content-Transfer-Encoding fields... </p>
  
  <p>Do you have any idea on how i might add the attributes?</p>