Does adding custom routes to WEB API make it non-REST? - rest

quick question - I was reading about RESTful services yesterday and someone had asked why SOAP wasn't RESTful. The answer was that SOAP doesn't have the 'generality of interfaces' property as is required by REST.
Then it struck me that I had been adding custom routes to my Web API like so:
Custom Routing with ASP.NET Web API
By doing that - I made my web API non-generic, thereby making the service non-RESTful, right? Not that that's a big deal, I just want to know whether I grasped the concepts correctly.

Well the rest rqeuires you to identify resoruces alone, not actions on them.
For example you might have an action addComment on Person, your route being
POST persons/2/addComment
This would make it non restful. The ideal way to do this would be:
POST persons/2/comments
For deleting a comment DELETE persons/2/comments/{commebntid}
So if you vary from this, your service becomes non restful. Its pretty hard to make a completely restful interface.
For example, if you have an object account, that you directly increment or decrement balance
accounts/2. You might have withdraw and deposit actions. POST accoints/2/withdraw. In rest, you need to either pass the balance as a parameter after decrementing it (PUT). There may be cases where you donot want to do this. You might not want to let the world know the balance of the user. Then you cant easily use put. You'd have to create a new entity: transaction and create transactions and calculate the account balance on the basis of transactions.
Ther eis no such thing as a generic API. You can't use amazons api and facebooks api interchangibly since the entities and operations are different. Don't worry too much about generalization. Just understand what the RESTful way is, and see if you can implemen it. If you have to tweak around it a bit, that's fine

Related

REST API design for resource modification: catch all POST vs multiple endpoints

I'm trying to figure out best or common practices for API design.
My concern is basically this:
PUT /users/:id
In my view this endpoint could by used for a wide array of functions.
I would use it to change the user name or profile, but what about ex, resetting a password?
From a "model" point of view, that could be flag, a property of the user, so it would "work" to send a modification.
But I would expect more something like
POST /users/:id/reset_password
But that means that almost for each modification I could create a different endpoint according to the meaning of the modification, i.e
POST /users/:id/enable
POST /users/:id/birthday
...
or even
GET /user/:id/birthday
compared to simply
GET /users/:id
So basically I don't understand when to stop using a single POST/GET and creating instead different endpoints.
It looks to me as a simple matter of choice, I just want to know if there is some standard way of doing this or some guideline. After reading and looking at example I'm still not really sure.
Disclaimer: In a lot of cases, people ask about REST when what they really want is an HTTP compliant RPC design with pretty URLs. In what follows, I'm answering about REST.
In my view this endpoint could by used for a wide array of functions. I would use it to change the user name or profile, but what about ex, resetting a password?
Sure, why not?
I don't understand when to stop using a single POST/GET and creating instead different endpoints.
A really good starting point is Jim Webber's talk Domain Driven Design for RESTful systems.
First key idea - your resources are not your domain model entities. Your REST API is really a facade in front of your domain model, which supports the illusion that you are just a website.
So your resources are analogous to documents that represent information. The URI identifies the document.
Second key idea - that URI is used by clients to cache representations of the resource, so that we don't need to send requests back to the server all the time. Instead, we have built into HTTP a bunch of standard ways for communicating caching meta data from the server to the client.
Critical to that is the rule for cache invalidation: a successful unsafe request invalidates previously cached representations of the same resource (ie, the same URI).
So the general rule is, if the client is going to do something that will modify a resource they have already cached, then we want the modification request to go to that same URI.
Your REST API is a facade to make your domain model look like a web site. So if we think about how we might build a web site to do the same thing, it can give us insights to how we arrange our resources.
So to borrow your example, we might have a web page representation of the user. If we were going to allow the client to modify that page, then we might think through a bunch of use cases (enable, change birthday, change name, reset password). For each of these supported cases, we would have a link to a task-specific form. Each of those forms would have fields allowing the client to describe the change, and a url in the form action to decide where the form gets submitted.
Since what the client is trying to achieve is to modify the profile page itself, we would have each of those forms submit back to the profile page URI, so that the client would know to invalidate the previously cached representations if the request were successful.
So your resource identifiers might look like:
/users/:id
/users/:id/forms/enable
/users/:id/forms/changeName
/users/:id/forms/changeBirthday
/users/:id/forms/resetPassword
Where each of the forms submits its information to /users/:id.
That does mean, in your implementation, you are probably going to end up with a lot of different requests routed to the same handler, and so you may need to disambiguate them there.

HATEOAS - REST is not truly REST

When REST API don't follow HATEOAS style, it is often referred your REST is not truly REST.
How come we can think of every possible request from clients can map to CRUD operations?
For example if the client(mobile) would like to send a reset password link to user for a given email id, how this shall be thought of as CRUD?
Very few REST advocates will argue that that REST should be applied to everything. I'm a big proponent of REST, but there are more than a few situations where not using HATEOAS is the most pragmatic move. Your example is one of them.
However, if you want to make this work in a RESTful manner, it's totally still possible.
For example, a lost password reset link might require a one-time authentication token. This token might be represented by a resource in a collection such as:
/users/xyz/auth-tokens
And perhaps you can initiate a lost-password email operation by creating a new 'auth-token' resource in that collection using POST.
Should you? I don't know! Can you? for sure!
Creating a PasswordReset resource is easy enough.
POST /password-resets
RPC minded people struggle to switch over to REST because they're used to doing things as RPC. :)
https://www.smashingmagazine.com/2016/09/understanding-rest-and-rpc-for-http-apis/

RESTful API callback for stand alone applications

I want to use a RESTful API of a web service that I have. However, I really don't know how the web service knows how to "give it" to the stand alone application since it does not have an URL. Is there a mechanism that makes URLs in this case not needed?
I think you need to read up a little more on what REST is and does. By its nature REST is a mechanism for requesting data. I.e. it is a "pull" not a "push". REST is typically used over Http - hence the need for a Url, In the same way you request/pull data everytime you visit a webpage.
If you wish to notify from one system to another as soon as change happen then you need to look at something other than REST. Alternatively your client can poll the REST service continually to check its response.

RESTful vs. SEO Urls

So I have a dilema here. Trying to build out a RESTful API. Which means I'd like to have resources defined and also require that consumers reference those resources by id.
For example, the typical {resourceName}/{id}?{querystring}
But the way of course a web UI works, for a ecommerce site is that naturally you have SEO-friendly urls.
So there is a mismatch in terms of application specific URLs where we have application context based urls, context here being an ecommerce site using SEO-friendly URLs. They wouldn't have stuff like /id in it 100% of the time. And actually our site doesn't have any ids whatsoever in the web UI's urls.
So when users go from page to page, we might have urls like www.ourdomain.com/cars/local/usa/ca/sunnyvale-cars. And sometimes we're talking about stripping the '-' or other characters out of the more seo friendly urls, after the UI devs send a request to lets say like above a state resource. I'd strip the city name out of 'sunnyvale-cars' if lets say I wanted info on that city so the UI team might send me '/cities?name=sunnyvale-cars' where our API would need to strip out the city name in order to do the query in the backend which to me just doesn't sound like something our API should be doing. It's also coupling our REST API to the web and web conventions...our REST API should be ignorant of any type of delivery mechanism so that our API can be reused for other apps or other APIs in our Business domain.
There might be times where the UI Engineering team, in fact a lot of times they'll only have URLs like this. There is no user action or lets say dropdown list where they can just grab an id. So they can't always request stuff for the next page by sending me a RESTful URI request every time as they may not have ids all the time. In other words, sometimes they'll have to instead request stuff like this: /states?name="ca" to get something related to that state just as a hypothetical example.
So how in the world do you even build a REST API if your UI team is telling you they won't have ids for everything?
From a REST purist's point of view no URI is inherently more RESTful than another as long as both use identify the resources. At least, I could not find anything about that in the original thesis.
However, if you find some structure fitting the purposes of your API better, you can create a second endpoint exclusively for the needs of your UI team. That endpoint would serve as a proxy and simply map the SEO-friendly structure to your API in possibly generic way.
Or, applications from the outside are just expected to do the rewriting or any app specific mapping-to-REST API "stuff" since it's really app specific in what that mapping looks like anyway, thus keeping the API ignorant of application specific details, domain logic, or even web conventions which the API should not care about or even know about.

Verbs in a RESTFUL (hypermedia) API

I'm having some trouble with RPC style verbs starting to appear in my API.
My question is: Is it okay to have these verbs, "Submit", "SendForApproval", "Accept" and "Reject" in a Restful API? Is that going against the Restful principles? What's best practice for naming these Actions?
Our business case:
I have an order. It starts out at status "pre-ordered". I want to then make a call to validate the order against our business logic. Depending on the validation results, I then either submit it or send it for approval. The approval process happens externally to our solution and then when it has been through the approval process the Api is called to mark the order as either Accepted or Rejected.
There is a bit more going on than simply updating statuses - we send things to print queues, spin off tracking documents etc.
So the URI's that we have defined are
https://api.site.com/orders // A list of orders
https://api.site.com/orders/{orderId} // An order
https://api.site.com/orders/{orderId}/ValidationErrors // Get a list of validation results
https://api.site.com/orders/{orderId}/Submit // Submit the order for processing
https://api.site.com/orders/{orderId}/SendForApproval // Send to supervisor
https://api.site.com/orders/{orderId}/Accept // Supervisor Accepts the order for processing
https://api.site.com/orders/{orderId}/Reject // Supervisor can Reject the order
You must avoid inserting verbs in your URIs as much as you possibly can. Furthermore, I disagree with user1438038, because the QueryString filters should be used for search purposes instead of specifying actions.
I believe that there're better approaches to solve this problem. First off, take into account that you shouldn't model your RESTful API in a way that it's highly tied to your business objects (supposing that you're using a OO approach). Moreover, remember that in a REST perspective, everything you expose is a resource rather than objects with its state and behavior.
I'm going to suggest you a different approach but I'm not sure if it's going to fulfill your system requirements but maybe it can be useful to give you some ideas. In your case, you can have multiple resources like PreOrders, Orders, Supervisors...
https://api.site.com/preorders
GET - Display all pre-orders.
POST - Create a new pre-order.
Creating a new order:
https://api.site.com/preorders/1
POST - approves the pre-order. This action's gonna create a new Order.
Displaying all orders that are waiting for approval (by the supervisor with ID=1).
https://api.site.com/supervisors/1/orders
Searching for approved and canceled orders:
https://api.site.com/supervisors/1/orders?status=canceled
https://api.site.com/supervisors/1/orders?status=approved
To cancel or approve an order:
https://api.site.com/supervisors/1/orders/1 (DELETE cancels the order)
https://api.site.com/supervisors/1/orders/1 (POST approves the order)
I'm unsure if it's the best approach to solve your problem but I'm pretty sure it's better than using verbs in your URI.
I'd be fine with that, we are using a very similar setup for order management.
However, another possibility would be passing an action parameter, such as:
https://api.site.com/orders/{orderId}/?action=accept
https://api.site.com/orders/{orderId}/?action=reject
...
The general idea of REST is to have resources (such as order or customer). What you want is more of a RPC semantics, but there is no right or wrong. Your approach is reasonable.
Not is a good practice have verbs in REST uris.
So, if you want change a status in any order, you may send a PUT/POST to https://api.site.com/orders/{orderId} updating only the values you want for your bussines logic.