WCF Streaming with REST on Mono

One of the problems with the mono framework is that streaming is not working properly. I tried to get it working myself and even tried to fix the framework myself. To much trouble as the solution is to use another approach called REST.

REST uses the url to submit parameters and the HTTP methods (GET, POST, PUT, DELETE) The supplied information is used to map te request to a service operation. Below is a sample of how to stream a file from a dotNET hosted REST service to a mono client.

The dotNET service is hosted in a console application. The configuration is below. Make sure to use the webHttpBinding.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <services>
      <!--Streaming over REST-->
      <service name = "FileService.ServiceImplementation.RESTService">
        <host>
          <baseAddresses>
            <add baseAddress = "http://localhost:999/Files/REST"/>
          </baseAddresses>
        </host>
        <endpoint
          address   = ""
          binding   = "webHttpBinding"
          contract  = "FileService.ServiceContract.IRESTService">
      </service>
    </services>
  </system.serviceModel>
</configuration>

REST makes use of the WebGet Attribute on the opartions in the ServiceContract. The UriTemplate maps the url to the service operation. Here the last and second last parts of the url are maped to parameters of the DownloadFile operation. The name of the part between the braces ({}) maps to the parameter with the same name. The result is a stream, more about that in the client code. I trust you can implement the operation yourself, just make sure to return a stream.

[ServiceContract]
public interface IRESTService
{
    [OperationContract]
    [WebGet(UriTemplate = "downloadfile/{name}/{id}")]
    Stream DownloadFile(string name, string id);
}

In the client (on mono) make use of the HttpWebRequest object. Build the url with the knowledge of the interface UriTemplate and read the response stream which is the stream returned from the fileservice.

using System.Net;
using System.IO;
// ...
var name = "myfile.txt";
var id = "12345";
// create the request url with the parameters inside the url
var address = string.Format("http://localhost:999/Files/REST/downloadfile/{0}/{1}", name, id);
// create the request object
HttpWebRequest request = WebRequest.Create(address) as HttpWebRequest;
// call to the REST service
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
    // Get the response stream  
    using (var stream = response.GetResponseStream())
    {
        // dosomething with the stream
    }
    // cleanup
    response.Close();
}

This solution uses default HTTP implementation and is supported on all platforms. Because the url is used for passing parameters the use of string paramaters is prefered. Complex types are not support, but could be passed in with the header of the request. These differences make REST less transparent but it is the price to pay if you need streaming on mono.

About erictummers

Working in a DevOps team is the best thing that happened to me. I like challenges and sharing the solutions with others. On my blog I’ll mostly post about my work, but expect an occasional home project, productivity tip and tooling review.
This entry was posted in Development and tagged , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.