Lib*_*orV 8 c# asp.net asp.net-mvc odata
我有一个基于MVC的网站,其中一个页面应该提供OData格式化的结果,同时还记录发送了表示结果中每条记录的字节数.我使用以下代码从DB获取结果:
[EnableQuery]
public IHttpActionResult GetRecords(ODataQueryOptions<Record> queryOptions)
{
DataProvider<Record> provider = GetRecordProvider();
...
return OK<IQueryable<Record>>(provider.Queryable);
}
Run Code Online (Sandbox Code Playgroud)
我试图通过它挂钩到OData格式化程序
config.Formatters.InsertRange(0, ODataMediaTypeFormatters.Create(new CustomODataSerializerProvider(), new DefaultODataDeserializerProvider()));
Run Code Online (Sandbox Code Playgroud)
哪里
public class CustomODataSerializerProvider : DefaultODataSerializerProvider
{
public override ODataEdmTypeSerializer GetEdmTypeSerializer(IEdmTypeReference edmType)
{
if (edmType.Definition.TypeKind == EdmTypeKind.Entity)
return new CustomODataEntityTypeSerializer(this);
else
return base.GetEdmTypeSerializer(edmType);
}
}
public class CustomODataEntityTypeSerializer : ODataEntityTypeSerializer
{
public CustomODataEntityTypeSerializer(ODataSerializerProvider provider)
: base(provider)
{
}
public override ODataProperty CreateStructuralProperty(IEdmStructuralProperty structuralProperty, EntityInstanceContext entityInstanceContext)
{
var property = base.CreateStructuralProperty(structuralProperty, entityInstanceContext);
if(property.Value == null) return null;
else return property;
}
public override void WriteObject(object graph, Type type, ODataMessageWriter messageWriter, ODataSerializerContext writeContext)
{
base.WriteObject(graph, type, messageWriter, writeContext);
}
public override void WriteDeltaObjectInline(object graph, IEdmTypeReference expectedType, ODataDeltaWriter writer, ODataSerializerContext writeContext)
{
base.WriteDeltaObjectInline(graph, expectedType, writer, writeContext);
}
public override void WriteObjectInline(object graph, IEdmTypeReference expectedType, ODataWriter writer, ODataSerializerContext writeContext)
{
int outputSize = 0;
base.WriteObjectInline(graph, expectedType, writer, writeContext);
writer.Flush();
Log(outputSize);
}
}
Run Code Online (Sandbox Code Playgroud)
我以为我能够找出WriteObjectInline
调用产生的输出长度,但无法弄清楚如何去做.
我也尝试了一种不同的解决方案
public class MeasuringJsonFormatter : ODataMediaTypeFormatter
{
public MeasuringJsonFormatter(IEnumerable<Microsoft.Data.OData.ODataPayloadKind> payloadKinds)
: base(payloadKinds)
{
SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/json"));
}
public override bool CanReadType(Type type)
{
return false;
}
private bool IsSupportedType(Type type)
{
return type==typeof(Record);
}
private bool IsSupportedCollection(Type type)
{
return
type.IsGenericType &&
IsSupportedType(type.GetGenericArguments()[0]) &&
typeof(IEnumerable<>).MakeGenericType(type.GetGenericArguments()[0]).IsAssignableFrom(type)
;
}
public override bool CanWriteType(Type type)
{
return IsSupportedType(type) || IsSupportedCollection(type);
}
public override System.Threading.Tasks.Task WriteToStreamAsync(Type type, object value, Stream writeStream, System.Net.Http.HttpContent content, System.Net.TransportContext transportContext)
{
return base.WriteToStreamAsync(typeof(string), Format(type, value, content), writeStream, content, transportContext);
}
public override System.Threading.Tasks.Task WriteToStreamAsync(Type type, object value, Stream writeStream, System.Net.Http.HttpContent content, System.Net.TransportContext transportContext, System.Threading.CancellationToken cancellationToken)
{
return base.WriteToStreamAsync(typeof(string), Format(type, value, content), writeStream, content, transportContext, cancellationToken);
}
private string Format(Type type, object value, System.Net.Http.HttpContent content)
{
if (IsSupportedType(type))
{
string result =JsonConvert.SerializeObject(value, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore });
Log(result.Length);
return result;
}
else if (IsSupportedCollection(type))
{
StringBuilder sb = new StringBuilder();
foreach (object item in (value as IEnumerable)) sb.Append(Format(type.GetGenericArguments()[0], item, content));
return sb.ToString();
}
else return "Unable to process type " + type.ToString();
}
}
Run Code Online (Sandbox Code Playgroud)
迷上了
config.Formatters.Insert(0, new MeasuringJsonFormatter(new ODataPayloadKind[] { ODataPayloadKind.Entry, ODataPayloadKind.Feed}));
Run Code Online (Sandbox Code Playgroud)
但这里的钩子似乎不起作用:我将断点设置为在其中定义的所有方法MeasuringJsonFormatter
,并且没有被击中.
任何人都可以给我一个指导方向吗?
我正在使用C#与Visual Studio 2010,MS ASP.NET MVC 5.2.3,MS ASP.NET Web API 2.2 for OData v4
小智 4
我不确定,但如果您实现自己的 ODataWriter 版本,那么您可以检查条目的长度。看一下这个示例:自定义 ODataWriter 的https://blogs.msdn.microsoft.com/odatateam/2015/01/05/tutorial-sample-odatalib-custom-payload-format/。在 CsvOutputContext 你得到
public void Flush()
{
this.stream.Flush();
}
Run Code Online (Sandbox Code Playgroud)
this.stream.Length
我想你之前可以尝试检查一下Flush
,但我没有测试过。
如果您想添加数据或更改序列化程序保存数据的方式,您需要在自定义 ODataWriter 中重写 WriteStart,如下所示:
public override void WriteStart(ODataFeed feed)
{
}
private void WriteEntry(ODataEntry entry)
{
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();
}
Run Code Online (Sandbox Code Playgroud)
this.context.Writer.Write
让您添加任何您喜欢的数据。只需查看我提供的示例链接即可。
为了保存 jpg 文件等二进制数据,您需要对其进行序列化。看这个:
private void WriteEntry(ODataEntry entry)
{
string file = @"C:\test.jpg";
byte[] data = File.ReadAllBytes(file);
using (MemoryStream fileStream = new MemoryStream(data))
using (Image i = Image.FromStream(originalms))
{
i.Save(this.context.Writer, System.Drawing.Imaging.ImageFormat.Jpeg);
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
532 次 |
最近记录: |