0

I'm trying to POST a request containing JSON from a Razor Pages app to a WCF service endpoint expecting a Json WebMessageFormat and Bare BodyStyle.The JSON passes just fine via Postman, but not when I send it through http-client. Wireshark also shows some extra bytes around JSON in the http-client produced packet that are not present in the Postman packet. Wireshark also reports this as line-based text data: application/json for the Postman packet. The .Net packet is JavaScript Object Notation: application/json.

Here's my C# code to send the JSON to the WCF endpoint:

var client = new HttpClient();
client.BaseAddress = new Uri("http://localhost:8000");

dynamic foo = new ExpandoObject();
foo.position = 1;

var content = new StringContent(Newtonsoft.Json.JsonConvert.SerializeObject(foo), System.Text.Encoding.UTF8, "application/json");

var request = new HttpRequestMessage(HttpMethod.Post, "http://localhost:8000/WCFService/ControllerV1/PostJSON");
request.Headers.Add("cache-control", "no-cache");
request.Headers.Add("Accept", "*/*");
request.Headers.Add("Connection", "keep-alive");
request.Content = content;


try
{
    var response = await client.SendAsync(request);
    response.EnsureSuccessStatusCode();
    string responseBody = await response.Content.ReadAsStringAsync();
}
    catch (HttpRequestException e)
{
    Console.WriteLine(e.Message);
}

And here's my WCF endpoint declaration:

[OperationContract, WebInvoke(Method="POST", RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare)]
void PostJSON(string jsonString);

I would expect the packets to produce the same response from the server, but, what appears to be the same string produces a response 200 when the packet is built by postman and a response 400 when built by .Net. I'm clearly missing something subtle here, but I can't seem to tease it out.

everette
  • 35
  • 7
  • HttpClient doesn't even what JSON is. It simply posts a StringContent. The contents of that string are generated by `JsonConvert.SerializeObject(foo)`. I suspect the real problem is the use of a WCF REST service instead of the common choice, Web API. WCF REST was a stopgap measure, quickly replaced by Web API – Panagiotis Kanavos Mar 28 '19 at 11:51
  • There's nothing wrong with either HttpClient or Json.NET. They are used in most if not *all* .NET Core projects to call HTTP sevices. Json.NET is the default serializer for Web API and ASP.NET Core. – Panagiotis Kanavos Mar 28 '19 at 11:56
  • @PanagiotisKanavos I agree that the original question seemed to indicate that I thought the fault was with http-client. I've updated both the title and the body of the question to better reflect the actual issue that I was experiencing. – everette Mar 29 '19 at 15:33

1 Answers1

0

There are 2 possible BodyStyle for request and response, wrapped or bare. When you specify wrapped body style the WCF service expects a valid json to be passed which in your case would be

//note that property name is case sensitive and must match service parameter name
{
    "jsonString": "some value"
}

And when you specify bare format the service expects only plain string value (in case of primitive type as yours) as the request like this

"some value"

When you serialize your object like this

dynamic foo = new ExpandoObject();
foo.position = 1;

string result = JsonConvert.SerializeObject(foo);

the result contains the following json

{
    "position":1
}

which corresponds to wrapped format and the service returns 400: Bad Request. All you need to do is to turn this json into valid json string value like this

"{\"position\":1}"

It can be done by repeated JsonConvert.SerializeObject call

dynamic foo = new ExpandoObject();
foo.position = 1;

string wrapped = JsonConvert.SerializeObject(foo);
string bare = JsonConvert.SerializeObject(wrapped);
var content = new StringContent(bare, System.Text.Encoding.UTF8, "application/json");
Alexander
  • 9,104
  • 1
  • 17
  • 41
  • Thanks, that worked! I wouldn't have thought rerun the serialization. So I guess the follow up question would be whether bare or wrapped is better, but questions [along those lines](https://stackoverflow.com/questions/20206069/restful-web-service-body-format) indicate that "it depends". – everette Mar 28 '19 at 12:57
  • @everette Yes it depends) *Bare* is better because less data is sent in request, but *Wrapped* body is a bit more intuitive and allows us to work with valid json object as we do while working with majority of api over the internet. – Alexander Mar 28 '19 at 13:04