Answered by:
WCF REST Service that accepts arbitrary JSON data into a Stream

Question
-
I want to create WCF REST Service that accepts arbitrary JSON data into a Stream, so that I can decode/parse myself into different data structures depending on the situation.
Here is a sample JSON body that I send in the request
{"intMemAvailableMax": 240, "intProjectRevision": 5, "blnCharging": 1, "intBatteryLevel": 80, "strUUID": "786234yugjhg4", "intMemAvailable": 105, "intDeviceId": 6170, "strIPAddr": "10.1.5.101", "strDescription": "A stream test"}
This what I have tried.
(I have also tried WebMessageBodyStyle.Bare)
[OperationContract] [WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped, UriTemplate = "DeviceHeartbeat/")] string DeviceHeartbeat(Stream s);
The client always has a http 400/404 error. If I remove the Stream parameter, the Client request works, but but the service has no Stream parameter to receive the stream in. On further reading I found that I can read the JSON into a string using:-
string JSONstring = OperationContext.Current.RequestContext.RequestMessage.ToString();
However, the string is not JSON, but an XML representation.
Is there a way to get a Stream or the JSON?
Then I could use JsonSerializer to Deserialize<T>(jsonReader) to T of my choosing on the fly.
Gadgetman Stewart
Wednesday, April 5, 2017 2:55 PM
Answers
-
For getting a Stream of body, you need to set {"Content-Type":"text/plain"} for the request instead of application/json.
Here is a simple code:
//Service Contract [OperationContract] [WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped, UriTemplate = "PostJsonBody/")] string PostJsonBody(); //Service implementation public string PostJsonBody() { var inputStream = OperationContext.Current.RequestContext.RequestMessage.GetBody<Stream>(); var sr = new StreamReader(inputStream, Encoding.UTF8); var str = sr.ReadToEnd(); return "Hello JSON Body"; }
Request in PostMan
POST /WCFRest/RestService.svc/PostJsonBody HTTP/1.1 Host: localhost Authorization: Basic di10YXpob0Bob3RtYWlsLmNvbTplRFdBUkQ5MDExMjE= Content-Type: text/plain Cache-Control: no-cache Postman-Token: d27820ba-31bb-4738-010f-aa321a1d1dfd {"intMemAvailableMax": 240, "intProjectRevision": 5, "blnCharging": 1, "intBatteryLevel": 80, "strUUID": "786234yugjhg4", "intMemAvailable": 105, "intDeviceId": 6170, "strIPAddr": "10.1.5.101", "strDescription": "A stream test"}
MSDN Community Support
Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.- Proposed as answer by Edward8520Microsoft contingent staff Thursday, April 6, 2017 7:21 AM
- Marked as answer by GadgetmanStewart Thursday, April 6, 2017 7:28 AM
Thursday, April 6, 2017 3:17 AM
All replies
-
For getting a Stream of body, you need to set {"Content-Type":"text/plain"} for the request instead of application/json.
Here is a simple code:
//Service Contract [OperationContract] [WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped, UriTemplate = "PostJsonBody/")] string PostJsonBody(); //Service implementation public string PostJsonBody() { var inputStream = OperationContext.Current.RequestContext.RequestMessage.GetBody<Stream>(); var sr = new StreamReader(inputStream, Encoding.UTF8); var str = sr.ReadToEnd(); return "Hello JSON Body"; }
Request in PostMan
POST /WCFRest/RestService.svc/PostJsonBody HTTP/1.1 Host: localhost Authorization: Basic di10YXpob0Bob3RtYWlsLmNvbTplRFdBUkQ5MDExMjE= Content-Type: text/plain Cache-Control: no-cache Postman-Token: d27820ba-31bb-4738-010f-aa321a1d1dfd {"intMemAvailableMax": 240, "intProjectRevision": 5, "blnCharging": 1, "intBatteryLevel": 80, "strUUID": "786234yugjhg4", "intMemAvailable": 105, "intDeviceId": 6170, "strIPAddr": "10.1.5.101", "strDescription": "A stream test"}
MSDN Community Support
Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.- Proposed as answer by Edward8520Microsoft contingent staff Thursday, April 6, 2017 7:21 AM
- Marked as answer by GadgetmanStewart Thursday, April 6, 2017 7:28 AM
Thursday, April 6, 2017 3:17 AM -
Thanks - {"Content-Type":"text/plain"} did the trick - I have tested this in my code and it works.
It is a pity that my clients (Android Apps) have to specify {"Content-Type":"text/plain"}
One would think that as the client is sending JSON, {"Content-Type":"application/json"} would be correct?
I prefer not to change the client - anyway around this?
Gadgetman Stewart
Thursday, April 6, 2017 4:57 AM -
If so, I suggest you try to loop through the below xml document which gets from "OperationContext.Current.RequestContext.RequestMessage.ToString()", and write the node name and value to json string.
<root type="object"> <intMemAvailableMax type="number">240</intMemAvailableMax> <intProjectRevision type="number">5</intProjectRevision> <blnCharging type="number">1</blnCharging> <intBatteryLevel type="number">80</intBatteryLevel> <strUUID type="string">786234yugjhg4</strUUID> <intMemAvailable type="number">105</intMemAvailable> <intDeviceId type="number">6170</intDeviceId> <strIPAddr type="string">10.1.5.101</strIPAddr> <strDescription type="string">A stream test</strDescription> </root>
MSDN Community Support
Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.Thursday, April 6, 2017 7:21 AM