2016-07-20 20 views
8

Tôi có một trang web dựa trên MVC với một trang sẽ phân phối kết quả được định dạng OData, đồng thời ghi lại số lượng byte được gửi đại diện cho mỗi bản ghi trong kết quả. tôi nhận được kết quả từ DB sử dụng mã này:Đo đầu ra từ phản hồi OData

[EnableQuery] 
public IHttpActionResult GetRecords(ODataQueryOptions<Record> queryOptions) 
{ 
DataProvider<Record> provider = GetRecordProvider(); 
... 
return OK<IQueryable<Record>>(provider.Queryable); 
} 

Tôi cố gắng để treo để formatter OData bởi

config.Formatters.InsertRange(0, ODataMediaTypeFormatters.Create(new CustomODataSerializerProvider(), new DefaultODataDeserializerProvider())); 

nơi

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); 
     } 
    } 

tôi nghĩ rằng tôi sẽ có thể tìm ra độ dài của đầu ra được tạo ra bởi cuộc gọi WriteObjectInline, nhưng không thể tìm ra cách thực hiện.

Tôi cũng đã thử một giải pháp khác nhau, sử dụng

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(); 
    } 

} 

nối bởi

config.Formatters.Insert(0, new MeasuringJsonFormatter(new ODataPayloadKind[] { ODataPayloadKind.Entry, ODataPayloadKind.Feed})); 

nhưng ở đây móc dường như không làm việc: Tôi đặt breakpoint cho tất cả các phương pháp quy định tại các MeasuringJsonFormatter, và không ai bị trúng.

Có ai có thể cho tôi hướng dẫn tìm kiếm không?

Tôi đang sử dụng C# với Visual Studio 2010, MS ASP.NET MVC 5.2.3, MS ASP.NET Web API 2.2 cho OData v4

+0

bạn đã tìm thấy giải pháp cho điều này chưa? –

+0

Bạn đã thử ý tưởng này http://weblogs.asp.net/fredriknormen/log-message-request-and-response-in-asp-net-webapi chưa? – DmitryBLR

Trả lời

4

Tôi không chắc chắn nhưng nếu bạn thực hiện phiên bản của riêng bạn ODataWriter sau đó bạn có thể kiểm tra độ dài của mục nhập. Hãy xem ví dụ này: https://blogs.msdn.microsoft.com/odatateam/2015/01/05/tutorial-sample-odatalib-custom-payload-format/ của ODataWriter tùy chỉnh. Trong CsvOutputContext bạn có

public void Flush() 
{ 
    this.stream.Flush(); 
} 

Tôi nghĩ rằng bạn có thể thử để kiểm tra this.stream.Length trước Flush, nhưng tôi đã không kiểm tra nó.

EDIT

Nếu bạn muốn thêm dữ liệu hoặc thay đổi cách serializer lưu dữ liệu của bạn, bạn cần phải ghi đè WriteStart bên ODataWriter tùy chỉnh của bạn như thế này:

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(); 
} 

this.context.Writer.Write cho phép bạn thêm whatver dữ liệu mà bạn thích . Chỉ cần nhìn vào liên kết ví dụ mà tôi đã cung cấp.

EDIT2

Để lưu dữ liệu nhị phân như tệp jpg, bạn sẽ cần phải tuần tự hóa dữ liệu đó. Nhìn vào điều này:

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); 
    } 
} 
Các vấn đề liên quan