Публикация пользовательского типа с помощью HttpClient

У меня есть собственный класс dto:

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

и контроллер с использованием Web Api (4.5.net framework)

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

На стороне клиента есть только 4.0 .net framework, поэтому я не смогу использовать метод 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?


person user1542666    schedule 10.12.2013    source источник


Ответы (2)


Конечно. Просто создайте себе новый класс 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);
person Darrel Miller    schedule 10.12.2013
comment
Спасибо за ваше решение. Я не уверен, что делает SerializeToStreamAsync, а TaskCompletionSource нужен тип значения результата. Должен ли это быть объект ввода или объект вывода? - person user1542666; 12.12.2013
comment
@user1542666 user1542666 Извините, мне пришлось на лету преобразовать if из .net45 в 4.0, и я забыл о <object>. Метод SerializeToStream копирует буферизованный поток в сетевой поток, когда это требуется для HttpClient. - person Darrel Miller; 12.12.2013
comment
Зачем использовать буферизованный поток? мы можем использовать сетевой поток и записать объект прямо в него? что-то вроде этого? 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(); } - person jeevjyot singh chhabda; 10.05.2019
comment
И почему бы не переопределить Dispose Method()? - person jeevjyot singh chhabda; 10.05.2019
comment
@jeevjyotsinghchhabda Да, можно. Обычно у меня есть привычка делать классы HttpContent автономными. Если объект значения изменился после создания объекта HttpContent, но до записи в сеть, то полезная нагрузка изменится. Но ваш подход верен на 100%. Я не перегружаю dispose, потому что этот класс не выделяет неуправляемую память. - person Darrel Miller; 13.05.2019

Создайте класс, наследуемый от 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;
person jeevjyot singh chhabda    schedule 10.05.2019