返回列表<;对象>;以Csv格式作为响应WCF C#

返回列表<;对象>;以Csv格式作为响应WCF C#,c#,wcf,csv,messageformat,mediatypeformatter,C#,Wcf,Csv,Messageformat,Mediatypeformatter,我想从WCF方法中以csv文件的形式返回类对象列表。我尝试使用这里给出的MediaTypeFormatter实现自定义格式化程序 但我无法在WCF服务方法中实现这一点。有没有办法在WCF中实现这一点?我可以在ResponseFormat中设置自定义格式设置程序吗?它会工作吗?我正在寻找直接将我的列表转换为csv的解决方案。我在服务接口中定义了简单的服务方法: [OperationContract] [WebInvoke(Method = "GET", BodyStyle = We

我想从WCF方法中以csv文件的形式返回类对象列表。我尝试使用这里给出的MediaTypeFormatter实现自定义格式化程序

但我无法在WCF服务方法中实现这一点。有没有办法在WCF中实现这一点?我可以在ResponseFormat中设置自定义格式设置程序吗?它会工作吗?我正在寻找直接将我的列表转换为csv的解决方案。我在服务接口中定义了简单的服务方法:

    [OperationContract]
    [WebInvoke(Method = "GET", BodyStyle = WebMessageBodyStyle.Bare, UriTemplate = "GetDNCList")]
    List<DNC> GetDNCList();
[运营合同]
[WebInvoke(Method=“GET”,BodyStyle=WebMessageBodyStyle.Bare,UriTemplate=“GetDNCList”)]
List GetDNCList();
此列表应作为csv文件提供给用户。自定义格式设置程序(以及
MediaTypeFormatter
)在ASP.NET Web API框架中使用,而不是在WCF中使用。在这个框架中,您需要使用
IDispatchMessageFormatter
来控制响应是如何格式化的。这篇文章详细介绍了如何实现这一点,下面的代码展示了一种为WCF实现CSV格式化程序的方法

public class StackOverflow_23979866
{
    public class DNC
    {
        public string Field1 { get; set; }
        public string Field2 { get; set; }
        public string Field3 { get; set; }
    }
    [ServiceContract]
    public interface ITest
    {
        [OperationContract]
        [WebInvoke(Method = "GET", BodyStyle = WebMessageBodyStyle.Bare, UriTemplate = "GetDNCList")]
        List<DNC> GetDNCList();
    }
    public class Service : ITest
    {
        public List<DNC> GetDNCList()
        {
            return new List<DNC>
            {
                new DNC { Field1 = "Value 1-1", Field2 = "Value 2-1", Field3 = "Value 3-1" },
                new DNC { Field1 = "Value 1-2", Field2 = "Value 2-2", Field3 = "Value 3-2" },
                new DNC { Field1 = "Value 1-3", Field2 = "Value 2-3", Field3 = "Value 3-3" },
            };
        }
    }
    public class MyWebHttpBehavior : WebHttpBehavior
    {
        protected override IDispatchMessageFormatter GetReplyDispatchFormatter(OperationDescription operationDescription, ServiceEndpoint endpoint)
        {
            if (operationDescription.Name == "GetDNCList")
            {
                return new MyListOfDNCReplyFormatter();
            }
            else
            {
                return base.GetReplyDispatchFormatter(operationDescription, endpoint);
            }
        }
    }
    public class MyListOfDNCReplyFormatter : IDispatchMessageFormatter
    {
        public void DeserializeRequest(Message message, object[] parameters)
        {
            throw new NotSupportedException("This is a reply-only formatter");
        }

        public Message SerializeReply(MessageVersion messageVersion, object[] parameters, object result)
        {
            List<DNC> list = (List<DNC>)result;
            StringBuilder sb = new StringBuilder();
            sb.AppendLine("\"Field1\",\"Field2\",\"Field3\"");
            foreach (var dnc in list)
            {
                // may need to escape, leaving out for brevity
                sb.AppendLine(string.Format("\"{0}\",\"{1}\",\"{2}\"", dnc.Field1, dnc.Field2, dnc.Field3));
            }

            Message reply = Message.CreateMessage(messageVersion, null, new RawBodyWriter(sb.ToString()));
            reply.Properties.Add(WebBodyFormatMessageProperty.Name, new WebBodyFormatMessageProperty(WebContentFormat.Raw));
            HttpResponseMessageProperty httpResp = new HttpResponseMessageProperty();
            reply.Properties.Add(HttpResponseMessageProperty.Name, httpResp);
            httpResp.Headers[HttpResponseHeader.ContentType] = "text/csv";
            return reply;
        }

        class RawBodyWriter : BodyWriter
        {
            string contents;
            public RawBodyWriter(string contents)
                : base(true)
            {
                this.contents = contents;
            }

            protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
            {
                writer.WriteStartElement("Binary");
                byte[] bytes = Encoding.UTF8.GetBytes(this.contents);
                writer.WriteBase64(bytes, 0, bytes.Length);
                writer.WriteEndElement();
            }
        }
    }
    public static void Test()
    {
        string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
        ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));
        ServiceEndpoint endpoint = host.AddServiceEndpoint(typeof(ITest), new WebHttpBinding(), "");
        endpoint.Behaviors.Add(new MyWebHttpBehavior());
        host.Open();
        Console.WriteLine("Host opened");

        WebClient c = new WebClient();
        Console.WriteLine(c.DownloadString(baseAddress + "/GetDNCList"));

        Console.Write("Press ENTER to close the host");
        Console.ReadLine();
        host.Close();
    }
}
公共类堆栈溢出\u 23979866
{
公共级DNC
{
公共字符串字段1{get;set;}
公共字符串字段2{get;set;}
公共字符串字段3{get;set;}
}
[服务合同]
公共接口测试
{
[经营合同]
[WebInvoke(Method=“GET”,BodyStyle=WebMessageBodyStyle.Bare,UriTemplate=“GetDNCList”)]
List GetDNCList();
}
公共类服务:ITest
{
公共列表GetDNCList()
{
返回新列表
{
新DNC{Field1=“Value 1-1”,Field2=“Value 2-1”,Field3=“Value 3-1”},
新DNC{Field1=“Value 1-2”,Field2=“Value 2-2”,Field3=“Value 3-2”},
新DNC{Field1=“Value 1-3”,Field2=“Value 2-3”,Field3=“Value 3-3”},
};
}
}
公共类MyWebHttpBehavior:WebHttpBehavior
{
受保护的重写IDispatchMessageFormatter GetReplyDispatchFormatter(OperationDescription OperationDescription,ServiceEndpoint)
{
if(operationDescription.Name==“GetDNCList”)
{
返回新的MyListoFdnReplyFormatter();
}
其他的
{
返回base.GetReplyDispatchFormatter(操作说明,端点);
}
}
}
公共类MyListOfDNCReplyFormatter:IDispatchMessageFormatter
{
public void反序列化请求(消息,对象[]参数)
{
抛出新的NotSupportedException(“这是一个仅回复的格式化程序”);
}
公共消息序列化回复(MessageVersion MessageVersion,对象[]参数,对象结果)
{
列表=(列表)结果;
StringBuilder sb=新的StringBuilder();
sb.追加行(“\'Field1\”、“'Field2\”、“'Field3\”);
foreach(列表中的变量dnc)
{
//可能需要逃避,为了简洁起见
sb.AppendLine(string.Format(“{0}\”、“{1}\”、“{2}\”、dnc.Field1、dnc.Field2、dnc.Field3));
}
Message reply=Message.CreateMessage(messageVersion,null,新的RawBodyWriter(sb.ToString());
Add(WebBodyFormatMessageProperty.Name,新的WebBodyFormatMessageProperty(WebContentFormat.Raw));
HttpResponseMessageProperty httpResp=新的HttpResponseMessageProperty();
reply.Properties.Add(HttpResponseMessageProperty.Name,httpResp);
httpResp.Headers[HttpResponseHeader.ContentType]=“text/csv”;
回复;
}
类别:BodyWriter
{
字符串内容;
公共RawBodyWriter(字符串内容)
:base(真)
{
this.contents=目录;
}
受保护的重写无效OnWriteByContents(XmlDictionaryWriter编写器)
{
writer.writeStarteElement(“二进制”);
byte[]bytes=Encoding.UTF8.GetBytes(this.contents);
writer.WriteBase64(字节,0,字节.长度);
writer.writeedelement();
}
}
}
公共静态无效测试()
{
string baseAddress=“http://“+Environment.MachineName+”:8000/服务”;
ServiceHost主机=新ServiceHost(类型(服务),新Uri(基地址));
ServiceEndpoint=host.AddServiceEndpoint(typeof(ITest),新的WebHttpBinding(),“”);
添加(新的MyWebHttpBehavior());
host.Open();
Console.WriteLine(“主机已打开”);
WebClient c=新的WebClient();
Console.WriteLine(c.DownloadString(baseAddress+“/GetDNCList”);
控制台。写入(“按ENTER键关闭主机”);
Console.ReadLine();
host.Close();
}
}

感谢您提供了出色的解决方案。但你们能告诉我,当我从浏览器发出get请求,或者在Fiddler或任何像RESTClient这样的插件工具上测试时,如何获取csv列表吗?在这种情况下,你们总是会得到一个.csv列表。