How to pass object to RESTful Service with GET request? - wcf

I have seen some posts in stackoverflow saying "sending list of items in the GET Method, is NOT allowed. It has to be accomplished via POST method only"
My code looks like
[OperationContract]
[WebGet(UriTemplate = "Employee/{emp}",RequestFormat=WebMessageFormat.Json)]
Employee GetEmpDetails(string emp);
and my input json object will be "{'id':1,'name':'test',....}
Is there any alternative way of achieving this issue.
Thanks

It is possible to send list of items with GET, it's just that out of the box only primitive values are supported. String values work just fine, but if you want to pass a complex object, you need to create a custom QueryStringConverter. The post at http://blogs.msdn.com/b/carlosfigueira/archive/2011/08/09/wcf-extensibility-querystringconverter.aspx explains how this can be done.

If you make your service RESTful you will most probably use HTTP PUT for Add method and HTTP POST for Update method. It is absolutely ok to pass object to these methods because objet will be part of HTTP request's body, not part of URI. URI is important for HTTP GET requests. HTTP GET requests should be only for data retrieval not for data modification.

You are mixing up HTTP GET/POST/... requests and REST GET/POST/PUT/DELETE/...
When you wanna request something RESTfully - you do a GET request. In your case I think it should look like
employee/{id}
or
employee/{name}
Please also note that usage of lowercase in the URI is preferable.
If you need multiple GET criteria, I think it could look like:
employee/id/{id}/name/{name}

Related

When to use RestRequest/RestResponse and when to use HttpResuest/HttpResponse?

When to use RestRequest/RestResponse and when to use HttpResuest/HttpResponse?
I am learning REST in Saleforce. I know there are methods like GET, POST, PUT, PATCH, DELETE.
But having confusion in these both and can I use Http request/Http Response instead of RestRequest/Restresponse ?
RestRequest/RestResponse are custom functions that allow you to listen for outside REST API requests from Apex code. You define a #RestResource annotated class and it functions much like the built in SF Rest API (although with the logic that you define). The different HTTP methods you mention are meant to respond (at a specific path) to different types of outside requests. A REST GET method should get a record. SF already has a REST API that follows these rules. They just enable you to write the logic to get the record (in this example) yourself, should you have some custom logic you wish to implement. Here is a link to the MDN docs that describe the different HTTP methods.
An HTTP request/response is when you wish to, from inside your APEX code, make a callout to some resource outside of SF.
In other words, think of RestRequest/RestResponse as a server method and HTTP as a client method.

Can we pass parameters to HTTP DELETE api

I have an API that will delete a resource (DELETE /resources/{resourceId})
THE above API can only tell us to delete the resource. Now I want to extend the API for other use cases like taking a backup of that resource before deleting or delete other dependant resources of this resource etc.
I want to extend the delete API to this (DELETE /resources/{resourceId}?backupBeforeDelete=true...)
Is the above-mentioned extension API good/recommended?
According to the HTTP Specification, any HTTP message can bear an optional body and/or header part, which means, that you can control in your back-end - what to do (e.g. see what your server receives and conventionally perform your operation), in case of any HTTP Method; however, if you're talking about RESTful API design, DELETE, or any other operation should refer to REST API endpoint resource, which is mapped to controller's DELETE method, and server should then perform the operation, based on the logic in your method.
DELETE /resources/{resourceId} HTTP/1.1
should be OK.
Is the above-mentioned extension API good/recommended?
Probably not.
HTTP is (among other things) an agreement about message semantics: a uniform agreement about what the messages mean.
The basic goal is that, since everybody has the same understanding about what messages mean, we can use a lot of general purpose components (browsers, reverse proxies, etc).
When we start trying to finesse the messages in non standard ways, we lose the benefits of the common interface.
As far as DELETE is concerned, your use case runs into a problem, which is that HTTP does not define a parameterized DELETE.
The usual place to put parameters in an HTTP message is within the message body. Unfortunately...
A payload within a DELETE request message has no defined semantics; sending a payload body on a DELETE request might cause some existing implementations to reject the request
In other words, you can't count on general purpose components doing the right thing here, because the request body is out of bounds.
On the other hand
DELETE /resources/{resourceId}?backupBeforeDelete=true
This has the problem that general purpose components will not recognize that /resources/{resourceId}?backupBeforeDelete=true is the same resource as /resources/{resourceId}. The identifiers for the two are different, and messages sent to one are not understood to affect the other.
The right answer, for your use case, is to change your method token; the correct standard method for what you are trying to do here is POST
POST serves many useful purposes in HTTP, including the general purpose of “this action isn’t worth standardizing.” -- Fielding, 2009
You should use the "real" URI for the resource (the same one that is used in a GET request), and stick any parameters that you need into the payload.
POST /resources/{resourceId}
backupBeforeDelete=true
Assuming you are using POST for other "not worth standardizing" actions, there will need to be enough context in the request that the server can distinguish the different use cases. On the web, we would normally collect the parameters via an HTML form, the usual answer is to include a request token in the body
POST /resources/{resourceId}
action=delete&backupBeforeDelete=true
On the other hand, if you think you are working on an action that is worth standardizing, then the right thing to do is set to defining a new method token with the semantics that you want, and pushing for adoption
MAGIC_NEW_DELETE /resources/{resourceId}
backupBeforeDelete=true
This is, after all, where PATCH comes from; Dusseault et al recognized that patch semantics could be useful for all resources, created a document that described the semantics that they wanted, and shepherded that document through the standardization process.

Handle JSON calls in WCF to single URL with method name contained in request body

We are replicating an existing service and need to offer the exact same contract.
Requests are posted to a single URL with the method name contained in the request body.
For example the request body of a call to LoginService.Login:
All calls will be made to: http://example.com/json
{"id": "","method":"LoginService.Login","params":{"aUserID":"flip","aPassword":"1234-613E-1240-C55D-9853F37A41B2"}}
How can we accomplish this within WCF? The response should also be JSON.
I didn't know what I wanted was called jsonrpc. Luckily somebody already tackled this problem:
Implement JSON-RPC in WCF

RESTful API design: inner interaction

Simple question. I read a bunch of articles about API design and didn't find the answer.
How should API's endpoints interact with each other?
For example, if I have 2 endpoints: /category/:name and /messages. What is the best way for example to check category existence from messages?
1) Database query from /messages handler like: SELECT * FROM categories WHERE name = 'test'?
or
2) HTTP request from /messages handler to that endpoint like: httpclient.get('/category/test') ?
or
3) Client should get all categories, get ID of particular category and send request to /messages with that category ID?
The question is simple but not an answer. One thing is sure, never use (2) solution. Requesting some data using http client when you can invoke a method will decrease performance and capacity of your API.
If checking existence of a particular category is required to create response in /messages then use (1) but instead of invoking SQL query invoke the same method as used to handle request to /category/test just invoke it locally not through HTTP.
Solution (3) is the REST-way when each endpoint is responsible only for one type of resources. The disadvantage is that it may require more HTTP requests from client to API.
You should design your application in a way that all the endpoint are calling internal APIs for performing the task. When you want to invoke one operation inside other then you should use the respective internal API instead of any other approach like calling http service.

Advantages of WebInvoke POST compared to WEBGET

hi i found one of the examples of wcf REST with a WEBINVOKE method just like the following
[OperationContract]
[WebInvoke(
BodyStyle=WebMessageBodyStyle.Bare,
Method="POST",
RequestFormat=WebMessageFormat.Xml,
ResponseFormat=WebMessageFormat.Xml,
UriTemplate="CreateStudent/{StudentName}/{Chair}/{AverageNote}")]
int Insert(string StudentName, string Chair, string AverageNote);
[OperationContract]
[WebGet(
BodyStyle= WebMessageBodyStyle.Bare,
RequestFormat = WebMessageFormat.Xml,
ResponseFormat = WebMessageFormat.Xml)]
Student[] GetAllStudents();
my question is can i use WEBGET method instead of WEBINVOKE just like below and what exactly is the difference betwenn WEBINVOKE POST and WEBGET,
as per my observation we are sending the parameters by appending query strings in the URI Templates for both WEbGet and WebInvoke POST, what are the advantages that we can get using WebInvoke POST which we can not get using WEBGET
[OperationContract]
[WebGet(
BodyStyle=WebMessageBodyStyle.Bare,
RequestFormat=WebMessageFormat.Xml,
ResponseFormat=WebMessageFormat.Xml,
UriTemplate="CreateStudent/{StudentName}/{Chair}/{AverageNote}")]
int Insert(string StudentName, string Chair, string AverageNote);
It is very big difference. First of all REST is usually used with these HTTP verbs:
GET - retrieving items
POST - inserting items
PUT - updating items
DELETE - deleting items
You should never use GET for anything else then retrieving items. Using HTTP GET for data modification is considered as a bad practice in whole web development. To trigger GET you just need to create link on the web page or simply type a URL to the browser. You will hit refresh 50 times and you have 50 same inserts. Data modification should be always done with POST. If you have form which triggers HTTP POST (Post cannot be triggered directly) and you hit refresh browser will usually ask you if you want the form to be submitted again = if you really want to post and process the data again to the server.
Another problem is that GET request can be cached and redirected but POST requests cannot.
This link should provide further insight into the answers provided:
http://blog.markkoltnuk.com/2011/02/14/understanding-wcf-webinvokewebget-attributes/
Lets explain, once and for all, what the difference between WebInvoke & WebGet.
WebGet (Commonly used to retrieve data)
The WebGet attribute exposes operations using the GET verb. You can access the endpoint is directly via a Web browser by typing the URI to the service into the address bar. Parameters can be sent within the URI either as query string parameters or embedded in the URI. The WebGet attribute should be used only for data retrieval due to its caching capabilities.
WebInvoke (Commonly used for data input/update)
The WebInvoke attribute exposes services using other HTTP verbs such as POST, PUT, and DELETE. POST is the default value but it can be changed by setting the Method property of the attribute. The WebInvoke attribute should be used only for data input/update.
To answer your question i would recommend you to understand the HTTP protocol semantics, especially HTTP Verbs, such as GET, POST, PUT, DELETE
HTTP GET is done to retrieve resource from any location and therefore the request should not alter the state of the resource.
HTTP POST is used to create and sometimes update content and hence has been used in the Insert method above.
If you run the WCF service above and see how are these request formed and server you would see that GET does not have a body payload whereas POST has. In case of POST the body contains the content that needs to be created\update.