/// <summary> /// Replace the inner HTTP response stream with substituteStream using reflection. /// /// The stream needs to be substituted because the request body needs to be translated before passed on to the base deserialization classes /// to take advantage of OData V4 model validation. Unfortunately, although it is guaranteed to exist, the message field is marked private /// in the ODataMessageWriter, so reflection must be used to modify it. /// </summary> /// <param name="writer">ODataMessageWriter which has not written yet.</param> /// <param name="substituteStream">Replacement stream.</param> /// <returns>The created stream.</returns> public static Stream SubstituteResponseStream(this ODataMessageWriter writer, Stream substituteStream) { FieldInfo messageField = writer.GetType().GetField("message", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy); object message = messageField.GetValue(writer); // Throw an exception if the message field does not exist in ODataMessageReader class anymore. if (message == null) { throw new Exception("The response body cannot be translated because the 'message' field does not exist in ODataMessageReader."); } FieldInfo requestMessageField = message.GetType().GetField("responseMessage", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy); var responseMessage = requestMessageField.GetValue(message) as ODataMigrationMessageWrapper; // Throw an exception if the responseMessage field does not exist in ODataRequestMessage class anymore. if (responseMessage == null) { throw new Exception("The response body cannot be translated because the 'responseMessage' field does not exist in ODataResponseMessage or it cannot be cast to ODataMigrationMessageWrapper."); } Stream originalStream = responseMessage.Stream; responseMessage.Stream = substituteStream; return(originalStream); }
/// <summary> /// Replace the inner HTTP response stream with substituteStream using reflection. /// /// The stream needs to be substituted because the request body needs to be translated before passed on to the base deserialization classes /// to take advantage of OData V4 model validation. Unfortunately, although it is guaranteed to exist, the stream is marked private /// in the ODataMessageReader, so reflection must be used to modify it. /// </summary> /// <param name="writer">ODataMessageWriter which has not written yet.</param> /// <param name="substituteStream">Replacement stream.</param> public static Stream SubstituteResponseStream(this ODataMessageWriter writer, Stream substituteStream) { FieldInfo messageField = writer.GetType().GetField("message", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy); object message = messageField.GetValue(writer); FieldInfo requestMessageField = message.GetType().GetField("responseMessage", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy); object requestMessage = requestMessageField.GetValue(message); FieldInfo streamField = requestMessage.GetType().GetField("_stream", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy); Stream originalStream = (Stream)streamField.GetValue(requestMessage); streamField.SetValue(requestMessage, substituteStream); return(originalStream); }