Serializing and Deserializing HttpRequestMessage Objects

Does anyone have any experience with serializing HttpRequestMessage objects? Trying with Json.net and partially working. However, JsonConvert.DeserializeObject fails due to problems with the StringContent construct: "Unable to find constructor to use type System.Net.Http.StringContent."

The following is a summary: I want to save the web request and issue it later, in case of temporary network problems or service unavailability, etc.

Example failed code:

var request = new HttpRequestMessage(HttpMethod.POST, "http://www.something.com"); request.Headers.Date = DateTimeOffset.UtcNow; request.Headers.AcceptLanguage.Add(new System.Net.Http.Headers.StringWithQualityHeaderValue("en-US")); request.Content = new StringContent("Hello World!"); request.Content.Headers.Add("x-some", "thing"); var result = JsonConvert.SerializeObject(request, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Objects, TypeNameAssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Full }); var deserializeRequest = JsonConvert.DeserializeObject<HttpRequestMessage>(result, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Objects }); 
+5
source share
3 answers

You can serialize / deserialize the corresponding parts of the HttpRequest using the following code example.

 var request = new HttpRequestMessage(HttpMethod.Post, "http://www.something.com"); request.Content = new StringContent("Hello World!"); var serializedRequestByteArray = new HttpMessageContent(request).ReadAsByteArrayAsync().Result; var tmpRequest = new HttpRequestMessage(); tmpRequest.Content = new ByteArrayContent(serializedRequestByteArray); tmpRequest.Content.Headers.Add("Content-Type", "application/http;msgtype=request"); var deserializedRequest = tmpRequest.Content.ReadAsHttpRequestMessageAsync().Result; 
0
source

I would suggest serializing only those objects for which you support implementation in your own code base.

For HttpRequestMessage, one of the reasons not to try to serialize is the fact that it implements IDisposable, which means that it may contain links to unmanaged resources. You can hardly predict this behavior with serializers.

In this case, I better go with the builder pattern:

 var builder = new MyRequestBuilder() .SetUrl("http://www.something.com") .SetMethod("POST") .SetStringContent("My content") .DefaultRequestSettings() // One benefit you can encapsulate some logic in builder. // ... using(HttpRequestMessage requestMessage = builder.Build(DateTime.UtcNow)) // probably need to renew Date header upon issuing the actual request { // issue request } 
+2
source

The problem is that StringContent does not have a default constructor. Therefore, when Json.Net tries to create a new StringContent, it cannot. I took a look at the custom JsonConverter to handle this, but it will not work because it is not visible that you can get the value assigned by StringContent. I.e

 public class StringContentConverter :JsonConverter { public override bool CanConvert(Type objectType) { return typeof(HttpContent).IsAssignableFrom(objectType); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { var jObject = JObject.Load(reader); //There nothing in here that says "Hello World!". The string content hides it. } } 

Essentially, you will need to save the input for your HttpRequest message in your own class.

0
source

Source: https://habr.com/ru/post/1205704/


All Articles