【问题标题】:Posting a Custom type with HttpClient使用 HttpClient 发布自定义类型
【发布时间】:2013-12-10 11:26:01
【问题描述】:

我有一个自定义的 dto 类:

public class myObject
{
    public string Id { get; set; }
    public string Name { get; set; }
}

和一个使用 Web Api(4.5 .net 框架)的控制器

[HttpPost]
public IHttpActionResult StripArchiveMailboxPermissions(myObject param)
{
    DoSomething(param);
    return OK();
}

客户端只有 4.0 .net 框架所以我将无法使用 PostAsJsonAsync() 方法。将对象从我的客户端传递到服务器的解决方案是什么?

我尝试过类似以下的方法:

var response = Client.SendAsync(new HttpRequestMessage<myObject>(objectTest)).Result;

但是它给我抛出了异常:

Could not load file or assembly 'Microsoft.Json, Version=2.0.0.0, 
Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. 
The system cannot find the file specified.

难道不能使用 Newtonsoft.Json 库吗?

【问题讨论】:

    标签: c# asp.net-web-api dotnet-httpclient


    【解决方案1】:

    当然。只需像这样为自己创建一个新的 HttpContent 类...

      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<object>();
                tcs.SetResult(null);
                return tcs.Task;
            }
    
            protected override bool TryComputeLength(out long length)
            {
                length = _Stream.Length;
                return true;
            }
        }
    

    现在您可以像这样将您的对象作为 Json 发送

      var content = new JsonContent(new YourObject());
      var httpClient = new HttpClient();
      var response = httpClient.PostAsync("http://example.org/somewhere", content);
    

    【讨论】:

    • 感谢您的解决方案。我不确定 SerializeToStreamAsync 做了什么,TaskCompletionSource 需要结果值的类型。应该是输入对象还是输出对象?
    • @user1542666 抱歉,我不得不即时将 .net45 转换为 4.0 并忘记了 &lt;object&gt;。 SerializeToStream 方法会在 HttpClient 需要时将缓冲的流复制到网络流中。
    • 为什么要使用缓冲流?我们可以利用网络流并将对象直接写入它吗?像这样的东西? protected override async Task SerializeToStreamAsync(Stream stream, TransportContext context) { StreamWriter = new StreamWriter(stream, new UTF8Encoding(false)); JsonTextWriter = new JsonTextWriter(StreamWriter) { Formatting = Formatting.None }; JsonSerializer.Serialize(JsonTextWriter, Value); //JsonTextWriter.Flush(); }
    • 为什么不重写 Dispose Method()?
    • @jeevjyotsinghchhabda 是的,你可以。我已经养成了让 HttpContent 类自包含的习惯。如果值对象在创建 HttpContent 对象之后但在写入网络之前发生更改,则有效负载将更改。但是你的方法是 100% 有效的。我不会重载 dispose,因为此类没有分配非托管内存。
    【解决方案2】:

    创建一个继承自 HttpContent 的类,它为您提供网络流,您可以直接写入它而不使用 memoryStream

    类似这样的:

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

    你会喜欢它

    var jsonSerializeContent = new JsonHttpContentSerializer(someContent);
    httpRequestMessage.Content = jsonSerializeContent;
    

    【讨论】:

      猜你喜欢
      • 2012-05-08
      • 1970-01-01
      • 2015-03-05
      • 2019-10-09
      • 1970-01-01
      • 1970-01-01
      • 2012-01-20
      • 2013-01-13
      • 1970-01-01
      相关资源
      最近更新 更多