用于导航属性的OData CSV序列化

时间:2017-01-31 03:38:15

标签: csv serialization text odata

我正在尝试开发OData序列化程序,以便我的OData REST API以逗号分隔值而不是JSON。

Karata Liu撰写了一篇精彩的文章[Tutorial & Sample] ODataLib Custom Payload Format,描述了如何做到这一点。

Liu的示例完全符合我对响应消息中需要返回的所有实体属性的要求,导航属性除外。对于导航属性,我想列出用逗号分隔的属性值以及主要实体的属性。

我不确定,但我认为我的问题是我覆盖了Microsoft的ODataOutputContext方法CreateODataFeedWriter(IEdmEntitySetBase entitySet,IEdmEntityType entityType):

internal sealed class CsvOutputContext : ODataOutputContext
{
    private Stream stream;

    public CsvOutputContext(
        ODataFormat format,
        ODataMessageWriterSettings settings,
        ODataMessageInfo messageInfo,
        bool synchronous)
        : base(format, settings, messageInfo.IsResponse, synchronous, messageInfo.Model, messageInfo.UrlResolver)
    {
        this.stream = messageInfo.GetMessageStream();
        this.Writer = new StreamWriter(this.stream);
    }

    public TextWriter Writer { get; private set; }

    public override ODataWriter CreateODataEntryWriter(IEdmNavigationSource navigationSource,
        IEdmEntityType entityType)
    {
        return new CsvWriter(this, entityType);
    }

    public override ODataWriter CreateODataFeedWriter(IEdmEntitySetBase entitySet, IEdmEntityType entityType)
    {
        return new CsvWriter(this, entityType);
    }

我没有对entitySet参数做任何事情,我想我需要将它连接到我的CSVWriter类(它来自Microsoft的ODataWriter类)。方法论证显然出于某种原因,但我不确定如何使用它。

我的CSVWriter类如下所示:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.OData.Core;
using Microsoft.OData.Edm;

namespace Hach.Fusion.FOART.Api.CsvMediaType
{
    internal class CsvWriter : ODataWriter
    {
        private CsvOutputContext context;
        private List<string> headers;

        public CsvWriter(CsvOutputContext context, IEdmEntityType entityType)
        {
            this.context = context;
            this.WriteHeader(entityType);
        }

        public override void Flush()
        {
            this.context.Flush();
        }

        public override void WriteEnd()
        {
        }

        public override void WriteStart(ODataFeed feed)
        {
        }

        public override void WriteStart(ODataEntry entry)
        {
            this.WriteEntry(entry);
        }

        private void WriteHeader(IEdmEntityType entityType)
        {
            this.headers = entityType.Properties().Where(p => p.Type.IsPrimitive()).Select(p => p.Name).ToList();
            foreach (var header in this.headers)
            {
                this.context.Writer.Write("{0},", header);
            }

            this.context.Writer.WriteLine();
        }


        private void WriteEntry(ODataEntry entry)
        {
            foreach (var property in entry.Properties)
            {
                //var property = entry.Properties.SingleOrDefault(p => p.Name == header);
                if (property != null)
                {
                    this.context.Writer.Write(property.Value);
                }

                this.context.Writer.Write(",");
            }

            //foreach (var header in this.headers)
            //{
            //    var property = entry.Properties.SingleOrDefault(p => p.Name == header);
            //    if (property != null)
            //    {
            //        this.context.Writer.Write(property.Value);
            //    }

            //    this.context.Writer.Write(",");
            //}

            this.context.Writer.WriteLine();
        }

        #region not implemented
        public override void WriteEntityReferenceLink(ODataEntityReferenceLink entityReferenceLink)
        {
            throw new NotImplementedException();
        }

        public override void WriteStart(ODataNavigationLink navigationLink)
        {

        }
        public override System.Threading.Tasks.Task FlushAsync()
        {
            throw new NotImplementedException();
        }
        public override System.Threading.Tasks.Task WriteEndAsync()
        {
            throw new NotImplementedException();
        }
        public override System.Threading.Tasks.Task WriteEntityReferenceLinkAsync(ODataEntityReferenceLink entityReferenceLink)
        {
            throw new NotImplementedException();
        }
        public override System.Threading.Tasks.Task WriteStartAsync(ODataNavigationLink navigationLink)
        {
            throw new NotImplementedException();
        }
        public override System.Threading.Tasks.Task WriteStartAsync(ODataEntry entry)
        {
            throw new NotImplementedException();
        }

        public override System.Threading.Tasks.Task WriteStartAsync(ODataFeed feed)
        {
            throw new NotImplementedException();
        }
        #endregion

调用WriteStart(ODataNavigationLink navigationLink)方法,但navigationLink参数中没有提供可以序列化的值。也没有提到被序列化的实体。有导航属性名称,但就是它。

我对此遗漏了一些东西。对于非导航属性,这似乎是直截了当的(尽管这可能是因为Liu的文章显示了这种方式)。

提前感谢所有阅读此内容的人。

1 个答案:

答案 0 :(得分:0)

你看过这个答案吗?它可能会指向正确的方向 https://stackoverflow.com/a/36835845/9840