Reading HttpRequest Body in REST WCF - json

I got a REST WCF Service running in .net 4 and I've tested the web service it is working and accepting HttpRequest I make to it. But I ran into a problem trying to access the HttpRequest body within the web service. I've tried sending random sizes of data appended on the HttpRequest using both Fiddler and my WinForm app and I can't seem to find any objects in runtime where I can find my request body is located. My initial instinct was to look in the HttpContext.Current.Request.InputStream but the length of that property is 0, so I tried looking in IncomingWebRequestContext that object doesn't even have a method nor properties to get the body of the HttpRequest.
So my question is, is there actually a way to access the HttpRequest request body in WCF?
PS:
The data inside the request body is JSON strings and for response it would return the data inside response body as JSON string too.

Much simpler, this answer on WCF + REST: Where is the request data? works fine.
Also, if your request body is deserializable, you can just pass a class. Barring some typos, this should work:
public class Banana
{
public string Colour;
public int Size;
}
...
[WebInvoke(
Method = "POST",
UriTemplate = "bananas",
ResponseFormat=WebMessageFormat.Json,
RequestFormat=WebMessageFormat.Json)]
string CreateBanana(Banana banana);
...
public string CreateBanana(Banana banana)
{
return "It's a " + banana.Colour + " banana!";
}
Doing POST with data {"Colour": "blue", "Size": 5} to this resource should return "It's a blue banana!".

Try with ((System.ServiceModel.Channels.BufferedMessageData)(((System.ServiceModel.Channels.BufferedMessage)((OperationContext.Current.RequestContext).RequestMessage)).MessageData)).Buffer
it has type System.ArraySegment<byte>
or read WCF + REST: Where is the request data?

Related

Spring Cloud Gateway => Read a Response Body and transform to a JSON object

I'm using Spring Cloud Gateway and I am stuck at doing, what I think, a simple thing.
I want to read a response Body and transform it to a Json Object so that I can read the value that I want.
I can extract cookies, headers, status BUT not the body.
So far my code is like that (in a custom filter) :
#Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
return chain.filter(exchange).then(Mono.defer(() -> {
ServerHttpResponse response = exchange.getResponse();
// Get the response body and transform it to a Json Object
Do U guys have an idea ?
Thank you very much.

Spring WebClient not processing JSON content

I have an app that uses WebClient to fetch JSON data from ComicVine as follows:
WebClient client = WebClient.builder()
.baseUrl(url)
.defaultHeaders(
headers -> {
headers.add(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE);
headers.add(HttpHeaders.USER_AGENT, "ComiXed/0.7");
})
.build();
Mono<ComicVineIssuesQueryResponse> request =
client
.get()
.uri(url)
.accept(MediaType.APPLICATION_JSON)
.retrieve()
.bodyToMono(ComicVineIssuesQueryResponse.class);
ComicVineIssuesQueryResponse response = request.block();
For a time this worked. But then, all of a sudden, it's throwing the following root exception when it executes:
Caused by: org.springframework.web.reactive.function.UnsupportedMediaTypeException: Content type 'application/json' not supported for bodyType=org.comixed.scrapers.comicvine.model.ComicVineIssuesQueryResponse
at org.springframework.web.reactive.function.BodyExtractors.lambda$readWithMessageReaders$12(BodyExtractors.java:201)
I'm not sure why it all of a sudden won't process JSON data. My unit test, which is explicitly returning JSON data and setting the content type properly:
private MockWebServer comicVineServer;
this.comicVineServer.enqueue(
new MockResponse()
.setBody(TEST_GOOD_BODY)
.addHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE));
Any ideas why this is the case? It's happening across multiple classes that use this same setup for WebClient and for testing.
After doing some digging, I added the following code to get the JSON as a String and then use ObjectMapper to convert it to the target type:
Mono<String> request =
client
.get()
.uri(url)
.accept(MediaType.APPLICATION_JSON)
.retrieve()
.bodyToMono(String.class);
String value = request.block();
ObjectMapper mapper = new ObjectMapper();
ComicVineIssuesQueryResponse response = mapper.readValue(value, ComicVineIssuesQueryResponse.class);
This quickly exposed the underlying problem, which was that two instance variables in the response were annotated with the same JSON field name. Once I fixed that, things started working correctly again.
you can parse the json content to string without calling block method.
option 1) Jackson2Tokenizer
option 2) put your code which is calling "objectMapper.readValue(..) .." inside map operator.

Can Web API HttpPost return ICollection

Newb to writing Web Services. Am using C#/ASP.Net with WebAPI. End goal is to receive JSON collection, and deserialize the data to database, and inform client application of any failed records, which client will log.
Can the HTTPPost return a collection of the failed rows (as serialized Json) through an IHttpActionResult or HttpResponseMessage, kind of like this:
[HttpPost]
public HttpResponseMessage Post([FromBody]List<Things> t)
{
// deserialize t and process to database
// list of failed records
ICollection<Thing> things= new List<Thing>();
things.Add(...);
things.Add(...);
string jsonFailedRows =
JsonConvert.SerializeObject(things, Formatting.Indented);
// Write the list to the response body
HttpResponseMessage response =
Request.CreateResponse(HttpStatusCode.OK, jsonFailedRows);
return response;
}
I saw this link: StackOverFlow, which says the I can do the following, but is this correct for a Post?
"The latter is done for you if you call the ApiController.Ok() method:
return Ok(jsonFailedRows);
And lastly, is there any way of using CreatedAtRoute to do so?
The solution posted in the linked response indeed answers this question.

Issue decoding JSON after Ext.Ajax.Request

I'm facing issues with ExtJS 4.1.3.
In my ExtJS controller, I call an ajax request like this :
Ext.Ajax.request(
{
url: '/my/url/method.do'
,timeout: 1800000
,jsonData: param
,success:function(response)
{
var jsonData = Ext.JSON.decode(response.responseText);
alert(jsonData);
// some code
}
,failure:function(response)
{
// some code
}
,scope:this
}
);
This is the method called in spring :
#RequestMapping(value = "/my/url/method.do")
public #ResponseBody String method(Locale userLocale, #RequestBody Param[] param) {
return "string" + "<br/>" + "string";
}
It works well on Google Chrome and IE but not on Firefox. Indeed, I get the following error :
Ext.Error: You're trying to decode an invalid JSON String: string<br/>string
And I don't know why it doesn't work because if I execute the following code in the Firefox console, it works :
Ext.JSON.decode("string<br/>string")
So if anyone could help me, I would be grateful !
Thanks for your answers.
This website http://jsonlint.com/ indicates "string<br/>string" as a valid JSON string. But it is a "false" JSON validation cause it is not proper JSON format.
I solved my problem adding produce="application/json" in the #EequestMapping annotation of the controller. So now Ext.JSON.decode() works even with Firefox.
I could also send back an object serializable with the ajax request and then decode the response to get the data (with my string in it) because Spring automatically serialize object to JSON.

PUT requests with Custom Ember-Data REST Adapter

I'm using Ember-Data 1.0.0.Beta-9 and Ember 1.7 to consume a REST API via DreamFactory's REST Platform. (http://www.dreamfactory.com).
I've had to extend the RESTAdapter in order to use DF and I've been able to implement GET and POST requests with no problems. I am now trying to implement model.save() (PUT) requests and am having a serious hiccup.
Calling model.save() sends the PUT request with the correct data to my API endpoint and I get a 200 OK response with a JSON response of { "id": "1" } which is what is supposed to happen. However when I try to access the updated record all of the properties are empty except for ID and the record on the server is not updated. I can take the same JSON string passed in the request, paste it into the DreamFactory Swagger API Docs and it works no problem - response is good and the record is updated on the DB.
I've created a JSBin to show all of the code at http://emberjs.jsbin.com/nagoga/1/edit
Unfortunately I can't have a live example as the servers in question are locked down to only accept requests from our company's public IP range.
DreamFactory provides a live demo of the API in question at
https://dsp-sandman1.cloud.dreamfactory.com/swagger/#!/db/replaceRecordsByIds
OK in the end I discovered that you can customize the DreamFactory response by adding a ?fields=* param to the end of the PUT request. I monkey-patched that into my updateRecord method using the following:
updateRecord: function(store, type, record) {
var data = {};
var serializer = store.serializerFor(type.typeKey);
serializer.serializeIntoHash(data, type, record);
var adapter = this;
return new Ember.RSVP.Promise(function(resolve, reject) {
// hack to make DSP send back the full object
adapter.ajax(adapter.buildURL(type.typeKey) + '?fields=*', "PUT", { data: data }).then(function(json){
// if the request is a success we'll return the same data we passed in
resolve(json);
}, function(reason){
reject(reason.responseJSON);
});
});
}
And poof we haz updates!
DreamFactory has support for tacking several params onto the end of the requests to fully customize the response - at some point I will look to implement this correctly but for the time being I can move forward with my project. Yay!
EmberData is interpreting the response from the server as an empty object with an id of "1" an no other properties in it. You need to return the entire new object back from the server with the changes reflected.