使用HttpClient发布自定义类型
使用HttpClient发布自定义类型
我有一个自定义的DTO类:\n
public class myObject { public string Id { get; set; } public string Name { get; set; } }
\n和一个使用Web Api(4.5 .net framework)的控制器\n
[HttpPost] public IHttpActionResult StripArchiveMailboxPermissions(myObject param) { DoSomething(param); return OK(); }
\n客户端只有4.0 .net framework,所以我不能使用PostAsJsonAsync()方法。如何将对象从客户端传递到服务器?\n我尝试了以下方法:\n
var response = Client.SendAsync(new HttpRequestMessage(objectTest)).Result;
\n然而,它抛出了异常:\n
无法加载文件或程序集“Microsoft.Json, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35”或其其中一个依赖项。 系统找不到指定的文件。
\n难道不能使用Newtonsoft.Json库吗?
问题出现的原因是需要在HttpClient中使用自定义的类型作为请求的内容,但是HttpClient默认只支持传递StringContent或ByteArrayContent类型的内容。
解决方法是创建一个继承自HttpContent的自定义类JsonHttpContentSerializer,该类可以将对象序列化成JSON字符串,并将其写入网络流中。具体实现如下:
using System; using System.IO; using System.Net; using System.Net.Http; using System.Text; using System.Threading.Tasks; using Newtonsoft.Json; namespace Http.Helper.Extensions { public class JsonHttpContentSerializer : HttpContent { private object Value { get; set; } public JsonHttpContentSerializer(Object value) { this.Value = value; } protected override async Task SerializeToStreamAsync(Stream stream, TransportContext context) { using (var streamWriter = new StreamWriter(stream, new UTF8Encoding(false), 1024, true)) { using (var jsonTextWriter = new JsonTextWriter(streamWriter) { Formatting = Formatting.None }) { var jsonSerializer = new JsonSerializer(); jsonSerializer.Serialize(jsonTextWriter, Value); jsonTextWriter.Flush(); } } } protected override bool TryComputeLength(out long length) { length = -1; return false; } } }
使用时,可以实例化JsonHttpContentSerializer类,并将自定义的对象作为参数传入。然后将该实例赋值给HttpRequestMessage的Content属性。示例如下:
var jsonSerializeContent = new JsonHttpContentSerializer(someContent); httpRequestMessage.Content = jsonSerializeContent;
通过以上方法,我们可以在HttpClient中传递自定义类型的内容,并将其序列化成JSON字符串进行传输。
问题的出现原因是:在使用HttpClient发送自定义类型时,需要将对象转换为Json格式并以流的形式发送给服务器。然而,HttpClient默认只能接受字符串或字节数组作为内容,无法直接处理自定义类型。
解决方法是:创建一个新的HttpContent类,并重写其SerializeToStreamAsync方法和TryComputeLength方法。在SerializeToStreamAsync方法中,将自定义类型对象转换为Json格式,并将其写入流中。在TryComputeLength方法中,计算流的长度。这样,就可以将自定义类型以Json格式发送给服务器。
具体实现如下:
public class JsonContent : HttpContent { private readonly MemoryStream _Stream = new MemoryStream(); public JsonContent(object value) { var jw = new JsonTextWriter(new StreamWriter(_Stream)) {Formatting = Formatting.Indented}; var serializer = new JsonSerializer(); serializer.Serialize(jw, value); jw.Flush(); _Stream.Position = 0; } protected override Task SerializeToStreamAsync(Stream stream, TransportContext context) { _Stream.CopyTo(stream); var tcs = new TaskCompletionSource
使用这个自定义HttpContent类,可以将对象以Json格式发送给服务器,示例如下:
var content = new JsonContent(new YourObject()); var httpClient = new HttpClient(); var response = httpClient.PostAsync("http://example.org/somewhere", content);
在这个示例中,我们创建了一个JsonContent对象,将自定义类型对象作为参数传入。然后,我们使用HttpClient的PostAsync方法发送请求,将JsonContent对象作为请求的内容。
对于问题中的其他问题,作者提供了一些解释和讨论。例如,关于SerializeToStreamAsync方法的作用和TaskCompletionSource的使用,作者解释了这个方法将缓冲流复制到网络流中,而TaskCompletionSource用于返回一个已完成的任务。
此外,还有关于为什么使用缓冲流而不是直接将对象写入网络流的讨论。作者解释说,使用缓冲流的原因是,如果在创建HttpContent对象后但在写入网络之前,值对象发生了变化,那么负载也会发生变化。但是,使用网络流直接写入对象的方法也是可行的。
最后,还有关于为什么不重写Dispose方法的讨论。作者解释说,不重写Dispose方法是因为这个自定义HttpContent类没有分配非托管内存,所以不需要对其进行释放。
总之,通过创建自定义的HttpContent类,可以解决使用HttpClient发送自定义类型的问题。该类将自定义类型对象转换为Json格式,并以流的形式发送给服务器。这种解决方法非常灵活,并且可以根据具体需求进行修改和扩展。