Link to home
Start Free TrialLog in
Avatar of true_soln
true_soln

asked on

What is best way using a WCF Service with Json interface to send file data and minimised packet size ?

Want to minimize the data packet sizes when sending data to a service
So not using Soap envelopes/xml using Json

I created a Json end point for the service
And have [WebGet] with UriTemplate's for most of the functions as they all rather simple

But what is best method to send binary data for files ?

And how can you unit test it with out need for host binding ?

<system.serviceModel>
    <services>
      <service name="AppService" behaviorConfiguration="DefaultServiceBehavior">
        <endpoint name="rest" address="" binding="webHttpBinding" contract="IService" behaviorConfiguration="restBehavior"/>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="DefaultServiceBehavior">
          <serviceMetadata httpGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
      </serviceBehaviors>
      <endpointBehaviors>
        <behavior name="restBehavior">
          <webHttp/>
        </behavior>
      </endpointBehaviors>
    </behaviors>
  </system.serviceModel>

Open in new window

public class AppService : IService
    {
		public String UploadFile(string fileName, Stream fileContents)
		{
			var buffer = new byte[10000];
			int bytesRead, totalBytesRead = 0;
			do
			{
				bytesRead = fileContents.Read(buffer, 0, buffer.Length);
				totalBytesRead += bytesRead;
			} while (bytesRead > 0);

			return String.Format("Uploaded file {0} with {1} bytes", fileName, totalBytesRead );
		}

		public string Data(string fileName, byte[] data)
		{
			return String.Format("Uploaded file {0} with {1} bytes", fileName, data.Length );
		}
	}

Open in new window

[TestClass]
	public class UnitTest1
	{
		static byte[] GetJsonArray(byte[] data)
		{
			StringBuilder sb = new StringBuilder();
			sb.Append('[');
			for (int i = 0; i < data.Length; i++)
			{
				if (i > 0) sb.Append(',');
				sb.Append((int)data[i]);
			}
			sb.Append(']');
			return Encoding.UTF8.GetBytes(sb.ToString());
		}

		static void SendRequest(string uri, string contentType, byte[] body)
		{
			HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(uri);
			req.Method = "POST";
			req.ContentType = contentType;
			req.GetRequestStream().Write(body, 0, body.Length);
			req.GetRequestStream().Close();

			HttpWebResponse resp;
			try
			{
				resp = (HttpWebResponse)req.GetResponse();
			}
			catch (WebException e)
			{
				resp = (HttpWebResponse)e.Response;
				var x = resp.ToString();
			}
			Console.WriteLine("HTTP/{0} {1} {2}", resp.ProtocolVersion, (int)resp.StatusCode, resp.StatusDescription);
			foreach (string headerName in resp.Headers.AllKeys)
			{
				Console.WriteLine("{0}: {1}", headerName, resp.Headers[headerName]);
			}
			Console.WriteLine();
			Stream respStream = resp.GetResponseStream();
			if (respStream != null)
			{
				string responseBody = new StreamReader(respStream).ReadToEnd();
				Console.WriteLine(responseBody);
			}
			else
			{
				Console.WriteLine("HttpWebResponse.GetResponseStream returned null");
			}
			Console.WriteLine();
			Console.WriteLine(" *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* ");
			Console.WriteLine();
		}

		[TestMethod]
		public void TestJsonSendData()
		{
			string baseAddress = "http://localhost:1590/AppService.svc";

			var image = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 };// 0, 1, 2 }; // some image array
			var dataLen = image.Length.ToString();

			//+ dataLen + "/"
			SendRequest(baseAddress + "/Data" , "application/json", GetJsonArray(image));
		}

		[TestMethod]
		public void TestJsonSendData2()
		{
			var uri = "http://localhost:1590/AppService.svc/UploadFile/Test.xml";

			var req = (HttpWebRequest)HttpWebRequest.Create(uri);
			req.Method = "POST";
			req.ContentType = "text/xml";
			Stream reqStream = req.GetRequestStream();
			string fileContents = "<hello>world</hello>";
			byte[] fileToSend = Encoding.UTF8.GetBytes(fileContents);
			reqStream.Write(fileToSend, 0, fileToSend.Length);
			reqStream.Close();
			var resp = (HttpWebResponse) req.GetResponse();
			Console.WriteLine("HTTP/{0} {1} {2}", resp.ProtocolVersion, (int) resp.StatusCode, resp.StatusDescription);
		}
	}

Open in new window

[ServiceContract]
	public interface IService
    {
		[OperationContract, WebInvoke(UriTemplate = "UploadFile/{fileName}")]
		String UploadFile(string fileName, Stream fileContents);
		
		[OperationContract]
		[WebInvoke(UriTemplate = "Data/{fileName}/{data}",RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
		String Data(string fileName, byte[] data);
	}

Open in new window

Avatar of Asim Nazir
Asim Nazir
Flag of Pakistan image

Hi,

If you can redesign, then  I think you should change your strategy a bit. Instead of embedding file in your service message. Why don't you store it on ftp/http and pass filePath in JSON message? Later you can download and process this file furhter...

I hope it helps.
Asim
ASKER CERTIFIED SOLUTION
Avatar of true_soln
true_soln

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of true_soln
true_soln

ASKER

A