【问题标题】:Return List<object> in Csv format as response WCF C#以 Csv 格式返回 List<object> 作为响应 WCF C#
【发布时间】:2014-06-01 12:28:31
【问题描述】:

我想从我的 WCF 方法中将我的类对象列表作为 csv 文件返回。我尝试使用此处给出的 MediaTypeFormatter 实现自定义格式化程序Custom formatter

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

    [OperationContract]
    [WebInvoke(Method = "GET", BodyStyle = WebMessageBodyStyle.Bare, UriTemplate = "GetDNCList")]
    List<DNC> GetDNCList();

此列表应以 csv 文件的形式发送给用户

【问题讨论】:

    标签: c# wcf csv messageformat mediatypeformatter


    【解决方案1】:

    自定义格式化程序(和MediaTypeFormatter)用于 ASP.NET Web API 框架,而不是 WCF。在此框架中,您需要使用IDispatchMessageFormatter 来控制响应的格式化方式。 http://blogs.msdn.com/b/carlosfigueira/archive/2011/05/03/wcf-extensibility-message-formatters.aspx 的帖子详细介绍了如何实现这一点,下面的代码显示了为 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();
        }
    }
    

    【讨论】:

    • 感谢您的出色解决方案。但是你能告诉我在从浏览器发出 Get 请求或在 Fiddler 或任何附加工具(如 RESTClient)上测试时如何获取 csv 列表吗?
    • 在这种情况下,您总是会得到一个 .csv 列表。
    猜你喜欢
    • 2016-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多