我正在尝试开发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的文章显示了这种方式)。
提前感谢所有阅读此内容的人。