Saturday, February 7, 2009

Fun With Functional Programming

Functional programming is seeing a lot of support these days so I thought I'd examine the differences between a few languages for common tasks. In this example, I want to search a list of numbers for only the even ones.

Here is how it can be done in C#:

int[] fullList = { 4, 31, 24, 2, 1, 13, 56 };
int[] evens = Array.FindAll(fullList, x => (x % 2 == 0));
Array.ForEach<int>(evens, x => Console.WriteLine(x.ToString()));

Now in F#
let fullList = [4; 31; 24; 2; 1; 13; 56]
let evens = fullList > List.filter (fun x -> (x % 2 = 0) ) > List.to_array
do Array.ForEach(evens, (fun x -> printfn "%d" x))

Pretty similar as you can see. Now lets see it in Ruby:

fullList = [ 4, 31, 24, 2, 1, 13, 56]
evens = fullList.select { x (x % 2 == 0)}
puts evens

Nice and simple. For comparison's sake, let's look at the non functional way of doing this in C# (I will use C# 2.0 here to make it at least a little easier):

int[] fullList = { 4, 31, 24, 2, 1, 13, 56 };
List<int> evens = new List<int>();
foreach (int num in fullList)
{
if (num % 2 == 0)
evens.Add(num);
}
foreach (int n in evens)
Console.WriteLine(n);

Functional programming offers great benefits when it comes to simplifying code and you aren't too limited to in your choice of languages to do it in. Granted there will be bigger differences when using more complicated examples but its nice to see how available it has become.

Wednesday, January 28, 2009

Uploading a file to RESTful WCF Services

.NET 3.5 makes it easy to create RESTful services that can be accessed via GETs but POST operations prove more difficult. I wanted to prove out a way to upload a file to a REST service by passing a stream and additional information about the file. The following is one way you can go about accomplishing this.

The Stream object is an easy way to send binary data but when used in a contract it is the only parameter allowed. To pass the additional information I simply made use of parameters passed in to the url.

Our contract:

[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "UploadFile")]
void UploadFile(Stream data);



Our service method will access the query string and read from the stream object:


public void UpoadFile(Stream data)
{

//get the query string passed in
OperationContext context = OperationContext.Current;
MessageProperties properties = context.IncomingMessageProperties;
HttpRequestMessageProperty requestProperty = properties[HttpRequestMessageProperty.Name] as HttpRequestMessageProperty;
string queryString = requestProperty.QueryString;


//put the values into a collection
NameValueCollection coll = HttpUtility.ParseQueryString(queryString);
string fname = coll["filename"];

//now read our data in chunks
int bytesread = 0;
int size = 8192;
using (FileStream fs = new FileStream(string.Format("./{0}", fname), FileMode.Create))
{
byte[] chunk = new byte[size];
bytesread = data.Read(chunk, 0, size);

while (bytesread > 0)
{
fs.Write(chunk, 0, bytesread);
bytesread = data.Read(chunk, 0, size);
}
}
}



Now that we have our service we can invoke it from the client:


//create our client web request object
HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(new Uri("http://localhost:49190/uploadservice/Service.svc/UploadFile?filename=test1.jpg"));
req.ContentType = "application/octet-stream";

req.Method = "POST";
Stream s = req.GetRequestStream();


//read our file into an array and write it out to our stream
using (FileStream fs = new FileStream("c:\\test1.jpg", FileMode.Open))
{
byte [] bytes = new byte[fs.Length];
fs.Read(bytes, 0, (int)fs.Length);
s.Write(bytes, 0, bytes.Length);
s.Close();
}


//invoke the request
WebResponse r = req.GetResponse();


Now we have a functioning upload service. The major downfall is the disconnect between the parameters passed in to the query string and the parameters assumed by the service. I'd love to hear other options that people have explored.