2016-07-20 2 views
8

OData 형식의 결과를 제공해야하는 페이지가있는 MVC를 기반으로하는 웹 사이트가 있고 결과의 각 레코드를 나타내는 바이트 수를 기록합니다.OData 응답의 출력 측정

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

내가

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

은 내가 할 수있을 것이라고 생각

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

하여 하나로, OData 포맷터에 훅을 시도 : 은이 코드를 사용하여 DB의 결과를 얻을 WriteObjectInline 호출에 의해 생성 된 출력의 길이를 알아낼 수 있지만이를 수행하는 방법을 알 수는 없습니다. 나는 MeasuringJsonFormatter에 정의 된 모든 메소드에 중단 점을 설정하고 :

은 또한 일을

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

그러나 여기 후크는하지 않는 것으로 구부려

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

} 

를 사용하여 다른 솔루션을 시도 아무도 맞지 않았다.

누구나 볼 수있는 방향을 알려줄 수 있습니까?

내가 비주얼 스튜디오 2010의 C#을 사용하고, MS ASP.NET MVC 5.2.3, 하나로, OData V4

+0

당신이 해결책을 찾았나요? –

+0

이 아이디어를 사용해 보셨습니까? http://weblogs.asp.net/fredriknormen/log-message-request-and-response-in-asp-net-webapi? – DmitryBLR

답변

4

에 대한 MS ASP.NET 웹 API 2.2은 잘 모르겠어요하지만 당신은 당신의 자신의 버전을 구현하는 경우 ODataWriter 다음 항목의 길이를 확인할 수 있습니다. 이 예제를 보자. 사용자 정의 ODataWriter의 https://blogs.msdn.microsoft.com/odatateam/2015/01/05/tutorial-sample-odatalib-custom-payload-format/. CsvOutputContext에서 당신은 당신이 Flush 전에 this.stream.Length을 확인하려고 수 있다고 생각

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

을 가지고,하지만 난 그것을 테스트하지 않았다.

편집

당신은 다음과 같이 사용자 정의 ODataWriter 내부 WriteStart를 오버라이드 (override) 할 필요가 시리얼 라이저가 데이터를 저장하는 방식으로 데이터를 추가하거나 변경하려면 :

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 당신이 당신이 좋아하는 whatver 데이터를 추가 할 수 있습니다를 . 내가 제공 한 예제 링크를 살펴보십시오. 당신이 그것을 직렬화해야합니다 JPG 파일과 같은 바이너리 데이터를 저장하기 위해

EDIT2

. 이것 좀 봐 :

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); 
    } 
} 
관련 문제