Serialize and deserialize HttpRequestMessage objects

不羁的心 提交于 2019-12-10 04:19:33

问题


Anyone have experience on serializing HttpRequestMessage objects? Trying with Json.net and it partially works. That said, JsonConvert.DeserializeObject fails due to constructure issues StringContent: "Unable to find a constructor to use for type System.Net.Http.StringContent".

The use case here is in short that I want to save the web request and issue it later, in case of temporary network issues or service unavailability etc..

Example code that is failing:

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

回答1:


I would suggest serializing only those objects for which you maintain implementation in your own codebase.

For HttpRequestMessage one of the reasons not to try serializing it is the fact it implements IDisposable, that means it can hold references to unmanaged resources. You can hardly predict it's behaviour with serializers.

In this case i'd better go with a 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:


The problem is that StringContent doesn't have a default constructor. So when Json.Net tries to go create a new StringContent it can't. I took a look writing a custom JsonConverter to handle this but that won't work either because it doesn't appear that you can get at the value you assigned to 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's nothing in here that says "Hello World!".  The string content hides it.
    }
}

Essentially you'll need to store the input for you HttpRequest message in your own custom class.




回答3:


It's possible to serialize/deserialize the relevant parts of an HttpRequest using the following example code.

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;  


来源:https://stackoverflow.com/questions/26611339/serialize-and-deserialize-httprequestmessage-objects

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!