COSM Trigger extracting JSON values using C# from an HTTP Post - c#

Trying to receive COSM Trigger HTTP Post via a C# RESTful service, not receiving the alert. I took the COSM API JSON payload and used it from a test client - that worked. When I setup my feed and either try the debug trigger test, or just force the trigger to fire normally, my REST service doesn't get called. If I try any form of test client the service processes the JSON POST just fine.
C# service is here:
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "cosm",
RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
string CosmAlert(CosmTrigger data);
Where CosmTrigger is my class mirroring the COSM Trigger fields.
My COSM feed is here.
I'm starting from the COSM portal to fire a trigger, Twitter based trigger works fine, the HTTP Post to my URL isn't. How to debug this?

A Cosm trigger currently doesn't send triggers as a JSON body, it actually sends a URL encoded request with the JSON trigger body encoded as a parameter called 'body'.
Using http://requestb.in on a test trigger, and viewing the raw output this shows the basic request looks like this:
POST /103s0dh1 HTTP/1.1
X-Request-Id: e05e9d699edbd5f584fc491cf9416df747be4df4
User-Agent: Cosm Deliverator (Axino/0.3.02) - https://cosm.com
Host: requestb.in
Content-Type: application/x-www-form-urlencoded
Content-Length: 918
Connection: close
body=%7B%22id%22%3A7443%2C%22url%22%3A%22http%3A%2F%2Fapi.cosm.com%2Fv2%2Ftriggers%2F7443%22%2C%22type%22%3A%22lt%22%2C%22threshold_value%22%3A%2220%22%2C%22timestamp%22%3A%222013-04-14T09%3A50%3A47.590044Z%22%2C%22environment%22%3A%7B%22id%22%3A57346%2C%22feed%22%3A%22http%3A%2F%2Fapi.cosm.com%2Fv2%2Ffeeds%2F57346%22%2C%22title%22%3A%22Macbook+Battery+Level%22%2C%22description%22%3A%22%22%2C%22private%22%3Afalse%2C%22location%22%3A%7B%22lat%22%3Anull%2C%22lon%22%3Anull%2C%22name%22%3A%22%22%7D%7D%2C%22triggering_datastream%22%3A%7B%22id%22%3A%22battery%22%2C%22url%22%3A%22http%3A%2F%2Fapi.cosm.com%2Fv2%2Ffeeds%2F57346%2Fdatastreams%2Fbattery%22%2C%22at%22%3A%222013-04-14T09%3A50%3A02.406927Z%22%2C%22value%22%3A%7B%22max_value%22%3A1724.0%2C%22min_value%22%3A0.0%2C%22value%22%3A%2226.28%22%7D%2C%22units%22%3A%7B%22type%22%3Anull%2C%22symbol%22%3A%22%25%22%2C%22label%22%3Anull%7D%7D%2C%22debug%22%3Atrue%7D
I'm not a C# expert unfortunately but I suspect the problem is something to do with the service not being configured to extract the JSON body from a standard urlencoded request body, but perhaps this might give a clue to how to figure out what is going wrong for someone who does know C#.

Tested and working code -
[OperationContract]
[WebInvoke(Method = "POST",
BodyStyle = WebMessageBodyStyle.WrappedRequest,
UriTemplate = "cosm")]
string cosmStream(Stream body);

Related

WCF REST: The incoming message has an unexpected message format 'Json'. Expected message format is 'Raw'

So I've seen many questions reagrding an error the other way around, but not this way.
In my WCF Service I've defined the method like:
[OperationContract]
[WebInvoke(BodyStyle = WebMessageBodyStyle.Bare, Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, UriTemplate = "v1/posttest")]
void PostTest(Stream incoming);
In my request header I've set Content-Type to application/json
So everything should work, right? However, I get a 400 Bad Request error and the notification you see in the question title.
Any help is appreciated. Thanks a lot!
Turns out, I should've just tried the most obvious thing... Removing the Content-Type header in my client solved the problem.
It still seems unintuitive to me, can anyone explain why WCF does that?
Very nice! Thank you a lot.
This runs perfectly:
read: {
url: "http://localhost:33473/Service2.svc/GetProfile", //contentType: "application/json; charset=utf-8", // tells the web service to serialize JSON
type: "POST", //use HTTP POST request as the default GET is not allowed for svc
}

Post (Error in deserializing body of request message for operation)

I have this method:
[OperationContract]
[WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.Wrapped, UriTemplate = "foo",
ResponseFormat = WebMessageFormat.Json)]
ResultChange Foo(int bar, String foobar);
I've downloaded a Firefox plugin (Poster) so I can easily send POST request.
But I get the
The server encountered an error processing the request. The exception
message is 'Error in deserializing body of request message for
operation 'ChangeDetails'. The OperationFormatter could not
deserialize any information from the Message because the Message is
empty (IsEmpty = true).'.
I've set the style to Wrapped as you can see, but that did not solve my issue. This was a solution provided here: Bad Request Error On REST service Method call with POST (json Data)? but did not solve it.
Update: I've succesfully sent a test() function, and it sent me back: "OK, the service is working". as it returns a string with that content.
What can I do to fix my issue?

how to send data from the client to the server using POST?

I am struggling sending data from my rest client to my rest server...
I have created a rest server sending xml to the client, and that works well. However, sending data from the client to the server, I am having a hard time.
Client:
_httpClientRead = new HttpClient("http://127.0.0.1:8000/");
var form = new HttpUrlEncodedForm();
form.Add("startDate", startDate);
_httpClientRead.Post("test", form.CreateHttpContent())
Server:
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "test")]
Meeting CreateNewMeeting(string startDate);
The problem seems to be the HttpUrlEncodedForm on the client side. If I am sending an empty HttpUrlEncodedForm object in the post request, the server receives the request. When adding the HttpUrlEncodedForm attributes, the server never receives the request, and there are no error messages!
What am I missing here? ( the server is returning xml )
How should the post data be sent to the server?
Thanks
I think it is a problem that you use HttpUrlEncodedForm on the client side, while the default on the server side is Xml. To make it clear set the request format on the server side to be RequestFormat = WebMessageFormat.Xml (set this in the WebIncoke attribute). After doing this you can configure your client to send valid xml. Also make sure you use the correct xml namespace. The easiest way to handle this is to use a function that will create the content automagically for you:
var httpContent = HttpContentExtensions.CreateDataContract(objectToSendToServer);
// And then send it using post:
_httpClient.Post("serviceUrl", httpContent);
Note that you also need set the DefaultHeader on the HttpClient to "application/xml".
WCF expects the data to be sent serialized by the DataContractSerializer. You cannot send other media types like application/x-www-form-urlencoded by default.
See this question on how to do it. Best way to support "application/x-www-form-urlencoded" post data with WCF?

Set Response format inside a function according to Accept header and not outside with ResponseFormat = WebMessageFormat.Json in REST

i am using the Plain old XML template from WCF REST Starter Kit Preview 2 to build a REST service and i would like to set the ResponseFormat inside the OperationContract, not outside(not with ResponseFormat = WebMessageFormat.Json) because i want to set it accordingly to the Accept Header in the Request. and ideally i would like to be able to set the RequestFormat from inside the OperationContract also, acording to the Content-Type header.
So, could anyone tell me how i can do it, or point me towards some examples.
chers,
Later Edit: so i don't want to have things like "format" in the UriTemplate, i just want one UriTemplate, no ResponseFormat (and no RequestFormat at some point) and the ResponseBody to be output according to the AcceptHeader
[WebHelp(Comment = "For Service testing purposes")]
[WebGet(UriTemplate = "Echo")]
[OperationContract]
public ResponseBody Echo()
You'll have to strip off most of the WCF REST code and rebuild it yourself. There is no support for content-type negotiation out of the box. I am lead to believe the starter kit has an example using their extensibility points, you may want to check with them.
http://damianblog.com/2008/10/31/wcf-rest-dynamic-response/ is a good place to start

Does the Content-Type of a POST or PUT request need to be 'application/x-www-form-urlencoded' in a WCF ReSTful service?

What I am trying to do is, seemingly, simple: send some POX via the request body, have the WCF service process it, and return a 201 status code. In my ServiceContract I have defined the following method:
[WebInvoke(Method = "PUT", UriTemplate = "/content/add", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Xml, RequestFormat=WebMessageFormat.Xml)]
[OperationContract]
Stream AddContent(Stream input);
The verb here doesn't matter; I could easily replace 'PUT' with 'POST' and wind up with the same result. The implementation of the above method is as follows:
public Stream AddContent(Stream input)
{
WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.Created;
}
Since what this method actually does is of little consequence I have omitted all of the procedural code. To test this functionality I fired up Fiddler and issued the following request:
User-Agent: Fiddler
Host: myhost.com
Content-Length: 771
Content-Type: text/xml && application/xml; charset: utf8
<xmlDataGoesHere></xmlDataGoesHere>
The supplied value for Content-Type is incorrect, I know, I am just using it to illustrate the Content-Type's that I have tried. If I click on 'Execute' in Fiddler the response code from my service is 400 Bad Request. It is worth noting that my service method is not actually getting hit in this secnario, the request dies before it even gets there. So after copious amounts of reading and process of elimination I changed the Content-Type to :
Content-Type: application/x-www-form-urlencoded
If I execute the Fiddler request now the status code returned from my service is 201 Created. Is there something I am missing as to why I can't set the Content-Type to anything but URLEncoded? I have tried tweaking the BodyStyle and RequestFormat properties in the ServiceContract but those did not have any impact on the outcome. Can anyone shed any light on why this is happening?
I think the problem is related to the fact that when you send XML to a WebHttpBinding, it detects that you are sending XML and tries to deserialize it. It ignores the fact that your signature is expecting a stream. There are workarounds that I have seen but I can't find the links at the moment. If I find them I'll update the post.
Take a look at this http://wcfrestcontrib.codeplex.com/
Ok I have figured this out and the issue I am having is "by design". I found the post 'WCF "Raw" programming model - receiving arbitrary data' over at http://blogs.msdn.com/carlosfigueira/ which led to the solution. The solution here was to create my own customBinding that will return the raw encoder all the time as the blog pointed out. Thanks for all the help.

Categories

Resources