2

I have a custom dto class:

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

and a Controller using Web Api (4.5 .net framework)

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

The client side only has 4.0 .net framework So I won't be able to use the PostAsJsonAsync() method. what is the solution to pass the object from my client to the server?

I have tried somethinig like the following:

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

however it throws me the exception:

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.

Isn't it possible to use the Newtonsoft.Json library?

Darrel Miller
  • 139,164
  • 32
  • 194
  • 243
user1542666
  • 160
  • 1
  • 1
  • 6

2 Answers2

9

Sure. Just create yourself a new HttpContent class like this...

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

and now you can send your object as Json just like this

  var content = new JsonContent(new YourObject());
  var httpClient = new HttpClient();
  var response = httpClient.PostAsync("http://example.org/somewhere", content);
Darrel Miller
  • 139,164
  • 32
  • 194
  • 243
  • Thanks for your solution. I am not sure what SerializeToStreamAsync does, and TaskCompletionSource needs the type of the result value. Should it be the input object or the output object? – user1542666 Dec 12 '13 at 17:04
  • @user1542666 Sorry about that, I had to convert if from .net45 to 4.0 on the fly and forgot about the ``. The SerializeToStream method will copy the buffered stream to the network stream when it is required by HttpClient. – Darrel Miller Dec 12 '13 at 17:08
  • Why use the buffered stream? we can make use of the network stream and write the object directly to it? something like this? `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(); } ` – jeevjyot singh chhabda May 10 '19 at 20:27
  • And why not override Dispose Method()? – jeevjyot singh chhabda May 10 '19 at 20:28
  • @jeevjyotsinghchhabda Yes you could. I have made a habit generally of making HttpContent classes self contained. If the value object changed after creating the HttpContent object but before writing to the network then the payload would change. But your approach is 100% valid. I don't overload the dispose because there is no unmanaged memory being allocated by this class. – Darrel Miller May 13 '19 at 14:34
0

Create a class inheriting from HttpContent, which gives you the network stream and you can write directly to it and not use the memoryStream

Something like this:

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

    }
}

and you would use like it

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