使用HttpClient发布自定义类型

16 浏览
0 Comments

使用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库吗?

0
0 Comments

问题出现的原因是需要在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字符串进行传输。

0
0 Comments

问题的出现原因是:在使用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();
        tcs.SetResult(null);
        return tcs.Task;
    }
    protected override bool TryComputeLength(out long length)
    {
        length = _Stream.Length;
        return true;
    }
}

使用这个自定义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格式,并以流的形式发送给服务器。这种解决方法非常灵活,并且可以根据具体需求进行修改和扩展。

0