what would be the best practice for allowing a WebAPI OData based webservice update an entire collection?
For example, we have an admin page that allows users to maintain a list of payment terms. We have created a controller that is based on the PaymentTerm entity, which allows the standard Get, Get by key, Put, Post, and Delete, for working with single instances of the PaymentTerm Entity. However, our UI team would like to retrieve a collection of payment terms (easily done with the standard Get collection), manipulate it locally, and then Put or Post the entire collection back to the server, rather than having to make a series of Put, Post, and Delete calls to the server.
I have tried creating an action method for this, and while I have managed to get it to work, it seems somewhat kludgy, as it requires an ID, as well as odata parameters (which contain the collection), and the ID is meaningless because at this point you are not working with an instance of a Payment Term, but an entire collection of them.
I could create a new controller solely for working with a collection of payment terms, but I'm not sure that would be much better, as it would end up having to have a base class declaration of
EntitySetController<PaymentTermCollection, int>
or the like, which would not make much sense as the collection would not have a key that had any meaning.
You should consider support $batch ( Standard part of OData ) in your web api using EntitySetApiControllers
Then you can submit a bag of changes including post-put-delete of multiple entities to your sever easily, within support of JayData , breeze , ...
Good luck
Related
I just want to clarify if it would be ok to use POST method to get some data from the Web API. The scenario is that the user has to pass a complex type e.g a UserInfo which has ID, Department, ETC to a Web Api function to get some extra details about user.
I can do this by passing the details in URI e.g http://apiuri/User?ID=1&Department=ABC& XXX and using a GET method or I can use a POST method and pass the UserInfo to it.
I prefer Post method however there are arguments in the team that Post should only be used for Creating or Modifying resources.
Is this correct? Should Post only be used for Creating/modifying a resource only?
many thanks
Typically Post methods are not guaranteed to be idempotent i.e. they can yield different results at different times. Now, this is not the case with your scenario. But without a wsdl, people really look to standards to figure out how a service would work. If you don't follow the standards, you might have a harder time explaining your api to your clients.
I am working on a new mobile app which will be talking to a rails server. Originally the idea was to remain restful and follow all conventions, however this goes against the client side best practices and performance of minimizing HTTP requests. I was wondering when you should remain restful and make only one api call per resource type, and when should you make one call which will update, add, remove and return a list of a few different resources.
For example, the app I am working on will be a scorekeeping app. Upon login, I return both the user information, a list of games that the scorekeeper can then edit, as well as all of the stats associated with each game. Since this list is returned in the first call, the view is immediately changed to the game list which is already pre-populated. This is quite fast.
Now from my understanding, to remain restful I would have to first make the login call(POST) for the user information, then make another(GET) call for the games list.
Another example would be uploading stats. Each stat has an action associated with it, whether its delete, update, or create. Currently all the stats are stored in a JSON which will send one POST call to the server. The server will then loop through the list and delete, update, or create the stats as needed. Now restfully I should be making a separate POST, DELETE, or PUT calls for each stat correct?
I have a good understanding of what restful is, but I'm failing to understand when/why to use it, and when to just combine everything into one api call to increase performance for the end user.
Do you have
(a) an actual, measured performance problem,
(b) a good and well-thought out argument for why you will have one, or
(c) a vague concern that REST is chatty?
It sounds like (c). Yes, REST can be chatty. Usually that's addressed with caching and good endpoint design.
Now from my understanding, to remain restful I would have to first
make the login call(POST) for the user information, then make
another(GET) call for the games list.
That would be traditional. It would not be unreasonable for the initial POST to do a redirect to get the games list. You can perform the GET conditionally (If-Modified-Since, If-None-Match), which will save bandwidth and server time. You can also set an explicit expiration time for the result of the GET to save some calls to the server.
Another example would be uploading stats. Each stat has an action
associated with it, whether its delete, update, or create. Currently
all the stats are stored in a JSON which will send one POST call to
the server. The server will then loop through the list and delete,
update, or create the stats as needed. Now restfully I should be
making a separate POST, DELETE, or PUT calls for each stat correct?
In this case, it sounds like the verb you want is PATCH. You can invoke PATCH on a collection endpoint, such as /stats, and include all the updates in one call. I suggest using the structure defined in RFC 6902 for PATCH requests.
I have an application that has different data sets depending on which company the user has currently selected (dropdown box on sidebar currently used to set a session variable).
My client has expressed a desire to have the ability to work on multiple different data sets from a single browser simultaneously. Hence, sessions no longer cut it.
Googling seems to imply get or post data along with every request is the way, which was my first guess. Is there a better/easier/rails way to achieve this?
You have a few options here, but as you point out, the session system won't work for you since it is global across all instances of the same browser.
The standard approach is to add something to the URL that identifies the context in which to execute. This could be as simple as a prefix like /companyx/users instead of /users where you're fetching the company slug and using that as a scope. Generally you do this by having a controller base class that does this work for you, then inherit from that for all other controllers that will be affected the same way.
Another approach is to move the company identifying component from the URL to the host name. This is common amongst software-as-a-service providers because it makes sharding your application much easier. Instead of myapp.com/companyx/users you'd have companyx.myapp.com/users. This has the advantage of preserving the existing URL structure, and when you have large amounts of data, you can partition your app by customer into different databases without a lot of headache.
The answer you found with tagging all the URLs using a GET token or a POST field is not going to work very well. For one, it's messy, and secondly, a site with every link being a POST is very annoying to work with as it makes navigating with the back-button or forcing a reload troublesome. The reason it has seen use is because out of the box PHP and ASP do not have support routes, so people have had to make do.
You can create a temporary database table, or use a key-value database and store all data you need in it. The uniq key can be used as a window id. Furthermore, you have to add this window id to each link. So you can receive the corresponding data for each browser tab out of the database and store it in the session, object,...
If you have an object, lets say #data, you can store it in the database using Marshal.dump and get it back with Marshal.load.
I'm building a RESTful API using Zend Framework via the Zend_Rest_Route. For uploading of files, should I use PUT or POST to handle the process? I'm trying to be as consistent as possible with the definition of the REST verbs. Please refer to: PUT or POST: The REST of the Story.
The way I understand this is that I should use PUT if and only if I'm updating the full content of the specified resource. I'll have to know the exact URL to use PUT. On the other hand, I should use POST if I'm sending a command to the server to create a subordinate of the specified resource, using some server-side algorithm.
Let's assume this is a REST API for uploading images. Does that mean I should use POST if the server is to manipulate the image file (i.e. create thumbnail, resize, etc); and use PUT if I just want to save the raw image file to the server?
If I use PUT to handle a file upload, should the process be as follows:
The user sends a GET request to retrieve the specific URL to upload the file by PUT.
Then the user sends a PUT request to that URL.
The file being uploaded is raw - exactly the one the user uploaded.
I'm quite new to this stuff; so hopefully I'm making sense here...
If you know the "best" way to do this, feel free to comment as well.
There seems to be quite a bit of misunderstanding here. PUT versus POST is not really about replace versus create, but rather about idempotency and resource naming.
PUT is an idempotent operation. With it, you give the name of a resource and an entity to place as that resource's content (possibly with server-generated additions). Crucially, doing the operation twice in a row should result in the same thing as if it was done just once or done 20 times, for some fairly loose definition of “the same thing” (it doesn't have to be byte-for-byte identical, but the information that the user supplied should be intact). You wouldn't ever want a PUT to cause a financial transaction to be triggered.
POST is a non-idempotent operation. You don't need to give the name of the resource which you're looking to have created (nor does a POST have to create; it could de-duplicate resources if it wished). POST is often used to implement “create a resource with a newly-minted name and tell me what the name is” — the lack of idempotency implied by “newly-minted name” fits with that. Where a new resource is created, sending back the locator for the resource in a Location header is entirely the right thing to do.
Now, if you are taking the policy position that clients should never create resource names, you then get POST being the perfect fit for creation (though theoretically it could do anything based on the supplied entity) and PUT being how to do update. For many RESTful applications that makes a lot of sense, but not all; if the model being presented to the user was of a file system, having the user supply the resource name makes a huge amount of sense and PUT becomes the main creation operation (and POST becomes delegated to less common things like making an empty directory and so on; WebDAV reduces the need for POST even further).
The summary: Don't think in terms of create/update, but rather in terms of who makes the resource names and which operations are idempotent. PUT is really create-or-update, and POST is really do-anything-which-shouldnt-be-repeated-willy-nilly.
For file upload, unless it is replacing an existing resource, definitely use POST.
In REST, POST is to create new resources, PUT to replace existing resources, GET to retrieve resources, and DELETE to delete resources.
Source: http://en.wikipedia.org/wiki/Representational_state_transfer#RESTful_web_services
REST isn't a standard so this can easily turn into a religious battle. AtomPub and OData standards which are considered to be "RESTful" do agree on this though: POST = creation while PUT = updates
The simple answer is you should use PUT instead of POST in your case since you will be replacing the entire content of the file. Take a look at PUT vs POST
I'll have to know the exact URL to PUT
to
No. You dont have to know the URL to PUT i.e. the PUT URI needn't be present before the PUT operation. If the resource doesn't exist, the resource is created. If the resource is already present, then the resource is replace with the new representation.
To quote the linked article:
PUT puts a page at a specific URL. If
there’s already a page there, it’s
replaced in toto. If there’s no page
there, a new one is created. This
means it’s like a DELETE followed by
an insert of a new record with the
same primary key
Let's assume that I have stores, shelves in a store, and products on a shelf. So in order to get a list of products on a shelf in a store, I'd use the following request:
GET http://server/stores/123/shelves/456/products
From here, how would I get an individual product? Should I use:
GET http://server/products/789
Or:
GET http://server/stores/123/shelves/456/products/789
The first method is more concise, since once you get a list of products, you don't really care which store it belongs to if you just want to view the details for a particular product. However, the second method is more logical, since you're viewing the products for a specific shelf in a specific store.
Likewise, what about a PUT/DELETE operation?
DELETE http://server/stores/123/shelves/456/products/789
Or:
DELETE http://server/products/789
What would be the correct way of designing a schema for a tree hierarchy like this?
P.S. If I'm misunderstanding something about the REST architecture, please provide examples on how I can make this better. There's way too many people who love to say "REST is not CRUD" and "REST is not RPC", then provide absolutely no clarifications or examples of good RESTful design.
I've noted 2 approaches to RESTful URI design: hierarchical & filtered
I feel hierarchical is overly verbose, has the potential for redundant endpoints (not DRY) and disguises in what resource's state you're really interested (after all, REST = representational state transfer).
I favor Simple URIs
Simple is elegant. I'd choose a URI structure like
GET http://server/products/789
because I am interested in the state of the product resource.
If I wanted all products that belonged to a specific shelf at a specific store, then I would do
GET http://server/products?store=123&shelf=456
If I wanted to create a product at a specific store on a specific shelf then I'd post
{
product: {
store: 123,
shelf: 456,
name: "test product"
}
}
via
POST http://server/products
Ultimately, it's tomayto, tomahto
REST doesn't require one over the other. However, in my own experience, it is more efficient to consume a RESTful API that maps single entities to single endpoints (eg: RestKit object mappings on iOS) instead of having an entity map to many different endpoints based on what parameters are passed.
About REST
As far as REST, it is not a protocol and has no RFC. It is tightly related to the HTTP/1.1 RFC as a way to implement its CRUD actions, but many software engineers will posit that REST does not depend on HTTP. I disagree and consider such as conjecture, because the original dissertation by UCI's Roy Fielding (http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm) explains the deep rooted connection of REST and HTTP/1.1. You may also enjoy Roy's opinion on the topic: http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven.
The principles defined by REST can be applied to other protocols, but REST was built for the internet and HTTP is the protocol for the world wide web.
REST vs RPC
RPC is all about making calls to remote functions and is verb-centric.
REST is all about using the CRUD convention to act on data depending on how the CRUD operation applies to a given data type and is noun-centric.
You can accomplish the same things with REST or RPC, but REST follows DRY principles because for every URI you can perform 4 actions whereas RPC requires an endpoint for each action.
PS
Much of this is my opinion and based on my experiences, but I hope it sheds some light on how you could most efficiently design a RESTful URI schema. As always, your specific goals and needs will affect your choices, but simplicity is always a good target for which to aim.
Creating a product should just be a POST to
http://server/product
Updating a product should just be a PUT to
http://server/product/$id
Getting a product should just be a GET to
http://server/product/$id
Deleting a product should just be a DELETE to
http://server/product/$id
You should use the http methods that are there for you to get more functionality out of a simpler uri structure. If creating a product requires a passing in a store and shelf as a requirement, then those should get passed in the body of your POST (or PUT if you're changing shelves).
When someone does a GET to http://server/product/$id, they will get back some kind of xml/json response, right? What does that look like? The incoming data for a create or update should be POSTed or PUT the same way in the body of the request. That is how you pass in the store and shelf, not via the uri. The uri should be as simple as possible and just point to the resource (product), using the http verbs to differentiate functionality.
If you want to be able to get the contents of shelf 23, you do a GET to
http://server/shelf/23
When you do, you get back a json / xml / custom media type document that has the shelf data and a collection of product elements with links back to their product uri.
If you want to be able to move product 23 from one shelf to another, you do a PUT to
http://server/product/23
In the body of the PUT you have the product in the representation of your choice, but with the updated shelf.
It's a weird mode of thinking at first, because you're not dealing with functionality across the entire system, but instead focusing on the resources (product, shelf, store) and using the http verbs to expose them to the universe.
Don't design a REST api based on an URL structure. Here is how I think you should go about designing a REST api.
Trying to define a REST interface without discussing what links will be contained in what resources is like discussing an RPC interface and ignoring parameters and return values.
Since products may be in several stores or several shelves (categories?), I'd have each product have a unique number regardless of its position in the hierarchy. Then use the flat product number. That makes the API more stable when some products are for instance moved in your store.
In short, don't add unneeded redundancy to your API. To get a shelve list a store ID is enough, for a product list a shelve ID is enough... etc.
it seems like you are trying to build many different use cases, but everything is getting built into one super service. It would be better to break it out.
http://server/product_info/123123 or http://server/product_info?product=123123
http://server/product_inventory?store=123&shelf=345
then you can also support:
http://server/product_inventory?store=123
then PUT and DELETE makes sense for changing inventory or adding a new product.