3

I'm at task to to send data in CSV format using a C# WCF RESTful (i.e. Web) Service. Currently, I have the code setup to send data in JSON.

How do I send the data in CSV format?

Note: This is not actually the set of files I'm using. It's just a sample to show how I'm constructing my service and to aid in modifying it for CSV output.

IService1.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;

namespace WcfService4
{
    // NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IService1" in both code and config file together.
    [ServiceContract]
    public interface IService1
    {
        [OperationContract]
        [WebInvoke(
            Method = "GET", 
            UriTemplate = "employees",
            RequestFormat = WebMessageFormat.Json,
            ResponseFormat = WebMessageFormat.Json,
            BodyStyle = WebMessageBodyStyle.Bare)]
        List<Employee> GetEmployees();
    }

    // Use a data contract as illustrated in the sample below to add composite types to service operations.
    [DataContract]
    public class Employee
    {
        [DataMember]
        public string FirstName { get; set; }

        [DataMember]
        public string LastName { get; set; }

        [DataMember]
        public int Age { get; set; }

        public Employee(string firstName, string lastName, int age)
        {
            this.FirstName = firstName;
            this.LastName = lastName;
            this.Age = age;
        }
    }
}

Service1.svc.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using System.Net;

namespace WcfService4
{
    // NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "Service1" in code, svc and config file together.
    public class Service1 : IService1
    {
        public List<Employee> GetEmployees()
        {
            // In reality, I'm calling the data from an external datasource, returning data to the client that exceeds 10 MB and can reach an upper limit of at least 30 MB.               

            List<Employee> employee = new List<Employee>();
            employee.Add(new Employee("John", "Smith", 28));
            employee.Add(new Employee("Jane", "Fonda", 42));
            employee.Add(new Employee("Brett", "Hume", 56));

            return employee;
        }
    }
}
user717236
  • 4,959
  • 19
  • 66
  • 102

1 Answers1

5

There are two alternatives to do that. The first is to write a new implementation of the IDispatchMessageFormatter, which knows how to understand CSV files and "deserialize" it into the appropriate type. You can find more information about it at http://blogs.msdn.com/b/carlosfigueira/archive/2011/05/03/wcf-extensibility-message-formatters.aspx.

The other, which is simpler, is to use the "raw programming model", in which your operation return type is declared as Stream, and your operation can return the CSV-formatted data. You can find more information about that mode at http://blogs.msdn.com/b/carlosfigueira/archive/2008/04/17/wcf-raw-programming-model-web.aspx.

carlosfigueira
  • 85,035
  • 14
  • 131
  • 171
  • 1
    Thank you very much. These are both great alternatives. My question for you is why can't I just set the method type to String and return type String? Or, the service will still serialize it in XML or JSON? – user717236 Jun 19 '13 at 18:09
  • I wanted to add that I did find a link that converts a JSON string to CSV (www.codeproject.com/Tips/565920/Create-CSV-from-JSON-in-Csharp), but that is probably only useful after the data has been serialized into JSON. I don't see any point in converting it to JSON just to convert it back to CSV, however. – user717236 Jun 19 '13 at 18:11
  • 2
    If the return type is `string`, it will be serialized as JSON (or XML), which is not what you want. – carlosfigueira Jun 19 '13 at 18:23
  • Thank you. One more related question: Could I, if I chose to, send a CSV file using SOAP-XML/MTOM, whereby the CSV is an attachment to the SOAP response? Is that possible, or this is only permissible for, say, images? – user717236 Jun 19 '13 at 18:37
  • 1
    You could send it via MTOM, yes. All you need to do is to send it as a `byte[]`, and it will be send as an attachment (if the size is larger than a certain threshold, which is around 768 bytes IIRC). – carlosfigueira Jun 19 '13 at 19:06
  • Thank you very much. If I send it as a byte[], doesn't that imply that interoperability goes out the window? I had thought that, while binary format keeps the size small, it doesn't play well when it comes to interoperability. Or, am I incorrect and sending as a byte[], employing MTOM, will not restrict the client to be using the same technology? For example, a client running PHP or Java can interpret the response with no problems. – user717236 Jun 19 '13 at 19:25
  • 1
    As long as the client understands MTOM, then they'll be able to read it properly. – carlosfigueira Jun 19 '13 at 21:17