MrEyes
MrEyes

Reputation: 13750

WCF REST - Posting a JSON string

When this "quick one hour" project came up I never thought that 2 days later I would be on Stackoverflow asking this question. However, here we go...

I have a number of external client applications (java, perl, php, c#) that are currently calling GET methods on a WCF REST service that returns JSON. This is working fine and is implemented exactly as you would expect.

I now have a requirement for these same applications to POST JSON into an new method on the original service interface. The C# app uses WebClient, Perl and PHP are using CURL, Java is using some magic that I am not involved with. All of them generate the JSON as a string and then call basic HTTP functionality to POST the data to an endpoint.

The issue is that the JSON we are using does not have a C# class associated with it (for reasons that can't be changed), as such we intend to use strings and json.net to parse/handle the incoming data. As an example, the endpoint could be:

https://magic.myserver.com/service/dataaggregator/

the external applications post a JSON string to this and in the underlying code we parse and handle as necessary.

So the question is a very simple one, how would this be implemented from a service interface perspective? I can handle serialisation/management of the JSON string within the service code without any problems the question is how do I get that string of JSON into the service code in the first place.

At the moment I am thinking that these can't be done using a "normal" WCF REST interface, rather I will have to implement a lower level HTTP listener where I can access the incoming post data directly.

Upvotes: 0

Views: 9030

Answers (4)

L.B
L.B

Reputation: 116188

If you want to go with HttpListener here is a sample code (using Json.Net)

HttpListener listener = new HttpListener();
listener.Prefixes.Add("http://*:8080/");
listener.Start();
Task.Factory.StartNew(() =>
{
    while (true)
    {
        HttpListenerContext context = listener.GetContext();
        ThreadPool.QueueUserWorkItem((o) =>
        {
            HttpListenerContext ctx = (HttpListenerContext)o;
            StreamReader rdr = new StreamReader(ctx.Request.InputStream);
            var postData = rdr.ReadToEnd();
            var dynJson = (JObject)JsonConvert.DeserializeObject(postData);

            foreach (var ch in dynJson.Children())
            {
                Console.WriteLine(ch);
            }

        }, context);
    }
});

Thread.Sleep(1000);
WebClient web = new WebClient();
web.UploadString("http://localhost:8080", 
                  JsonConvert.SerializeObject(new { ID=1,Name="name1" } ));

Upvotes: 0

Quintium
Quintium

Reputation: 497

If it is a .Net 4.0 WCF project then JSON is supported directly:

http://msdn.microsoft.com/en-us/library/ee354381.aspx

Locate section "Message Format Selection". Just make sure Accept header is set to application/json

Upvotes: 0

Regfor
Regfor

Reputation: 8101

With ASP.NET WebAPI use Anonymous and Weakly-Typed JSON Objects

Look here in section "Anonymous and Weakly-Typed JSON Objects": http://www.asp.net/web-api/overview/formats-and-model-binding/json-and-xml-serialization

Actually it uses JSON.NET so you are able to do it with older .NET REST Technologies. But I am sure that when dealing with mature JSON parsers (not only on .NET), it's possible to parse arbitrary JSON structure like it does Json.NET

UPD: Take a look at this link

http://www.hanselman.com/blog/NuGetPackageOfTheWeek4DeserializingJSONWithJsonNET.aspx

You can even deal with JObject class from Json.NET as dynamic. Parsing Json string can produce JObject

Upvotes: 0

Cheeso
Cheeso

Reputation: 192657

If you want to accept arbitrary JSON, look here:

http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/071f73bb-e141-4a68-ae61-05635382934f

If that's not what you want, then you may need to clarify your goals in the question.

See also, https://stackoverflow.com/a/7360619 and https://stackoverflow.com/a/2330219

The service interface is like this:

[OperationContract]
public Whatever  MyMethod(DataPacket rawJSON)
{ 
     ....
}

[DataContract]
public class DataPacket
{
  [DataMember]
  public JsonDictionary Registration { get; set; }
}

...where JsonDictionary is defined according to this answer.

You can also code the method to accept a stream, like this:

[OperationContract]
public Whatever  MyMethod(Stream rawJSON)
{ 
     ....
}

...and parse the JSON yourself, according to this answer.

Upvotes: 1

Related Questions