Routes for MVC 4 Web APIs? - asp.net-mvc-routing

In my initial stab at creating a MVC4 Web API. I've noticed a few things about the way routes are handled that seems a little off:
Controllers no longer ever have more than 4 actions?
A resource that only supports one HTTP verb still gets it's very own controller?
The route hierarchy tends to be very flat, OR
An extremely large number of routes must be specified/maintained compared to MVC apps for humans.
I've created fairly large sites that use only two or three routes, but I'm just starting on my API and I'm up to almost a dozen. I guess APIs by their nature lend themselves to deeper URLs than websites, but this seems a little excessive.
I feel like I'm missing a namespace somewhere or a routing convention. I attribute nearly all of this to the fact that action names are no longer part of the route, just the HTTP method. Is there a way to support routes by anything other than parameter matching, controller name, and HTTP method?

You can modify the routing in Global.asax. The default is set to:
routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
But you could change it for example to use the action name:
routes.MapHttpRoute(
name: "ActionApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
For more information on custom routing in MVC WEb API look at this article.
Update based on comments
Above was the answer to the question, "can I change the routing?" The short answer is yes, but as was pointed out in another answer you may not want to and maintain a good REST API. MVC Web API with it default routing maintains the basic REST concept that you are working on resources, with the controller representing the resource. In your other question you give the example:
DELETE /account/1234/note/321 <- delete note 321 on account 1234
Where you want to delete a note on account 1234. In this case the resource you are working on is a note. A better representation for this would be to use query string so your API for this example would look like this:
DELETE /note/321?account=1234 <- delete note 321 on account 1234
This way you do not need to mess with the routing and it is clear that the resource being acted upon is a note with filters being used. But I would also question whether adding this explicit filter (i.e. where clause) is necessary if the id for note is unique for the whole application and not just for a specific account.

The Web API is designed and tailored for RESTFull services, think of the controller as the service name. GET/PUT/POST/DELETE are mapped to the controller action who's name contains the verb, by convention.
If you are not trying to do something RESTFull, then I would use an HTTPController instead. As you likely noticed, you can mix them in the same project with separate routes.

Related

REST API - Add item as relational resource to another resource

I have been wondering what would be the best approach when adding a resource that is linked to another resource.
I have two objects:
+ Employee: An employee for an IT company
+ Skill: The employee set of technology skills; for example, Java.
Someone can create an employee via REST with the following path:
POST: /employee
Though someone could create a Skill object by itself, similar to creating an Employee object, but it needs to be linked to an Employee, thus...
PATCH: /employee/{employeeId}/skill
This path will create a new Skill to the Employee object, but this is where I am wondering if I am doing something wrong.
Usually when you create a new resource, you use the POST verb, but at the same time I am also updating part of the Employee resource thus it acts like a PATCH verb. Plus, a POST verb should be free from any parameters like {employeeId}.
What would be the best approach / practice when documenting REST API with this scenario?
What would be the best approach / practice when documenting REST API with this scenario?
It may be worth reviewing Jim Webber's 2011 talk.; in short, if you are doing REST, then you are passing around documents -- the useful work performed on your domain model is a side effect of document manipulation.
If you are using PUT/PATCH, then you are fundamentally performing remote authoring -- which is to say, you are asking the server to accept your local copy of a document. And that's fine, even when the server, in accepting your edits, will also be changing its representation of other resources.
You could instead design your application domain protocol so that you are making remote edits to the employee document directly, or even POST-ing edits to that resource, which in turn could have side effects on a skill resource.
Remember, the first application designed using the REST architectural style was the World Wide Web; the most common media-type for defining domain application protocols was HTML, and the only unsafe request method natively supported by HTML was POST -- and this was catastrophically successful.
So POST is fine.
Where things tend to get tricky is when you are trying to support generic components that want to take advantage of caching. Then, you need to be thinking about the rules for invalidating cached data when you design your protocol.

How to do versioning in the REST API URI address?

I'm looking at ways to version the URIs of a Spring REST API because, in the case of launching a new application, the REST API handles the new application and supports the old application requests for a certain period. But I am in doubt as to what database, system entities, and URIs are in general whenever a version is added to a URI.
Example:
No version, a request to fetch all users:
http://host:8080/api/users
With versioning:
http://host:8080/v1/users
http://host:8080/v2/users
http://host:8080/v1/products
I was thinking of making a User entity and when defining the attributes I note them as not mandatory and the entity is always the most current version. For the 'v2' version of the URI I create a UserV2DTO so that it primarily serves the User entity doing the validations with the required annotations. For the 'v1' version of the URI, let's say that the user does not have the 'dateBirth' attribute and in this way it receives a UserV1DTO that does not have the dateBirth attribute and at the time of converting the DTO to Entity the Entity.dateBirth attribute is null because is required.
What I want to know is if this is a correct form of versioning, because in the database the attributes are not mandatory and the validation of the mandatory is in the DTO? Also I want to know if all the URIs of all the resources need to be changed to the last version or if in the case of 'products' it can stay in V1 until one day it is necessary to change only it?
How to do versioning in the REST API URI address?
Real answer? Any way you want, consistent with your local conventions.
In REST, URI are just identifiers; effectively they are keys used to look up information in a cache. Embedding information in the URI is done at the discretion of the server, and for its own exclusive use.
Roy Fielding, who defined REST while leading the specification work for HTTP/1.1, wrote
The reason to make a real REST API is to get evolvability … a "v1" is a middle finger to your API customers, indicating RPC/HTTP (not REST)
As an example, consider Google -- how many different implementations of web search do you suppose that they have had, over the years? But the API itself has been stable: navigate to the bookmarked home page, enter data in the search form, submit -- dispatching the data to whatever URI was described in the form meta data.
Of course, even if you aren't doing REST, you might still want a URI design that is sane. Using path segments to partition your resource hierarchy has advantages when it comes to relative URI, because you can then use dot-segments to produce other identifiers in the hierarchy.
/v1/users + ../products -> /v1/products
Your life down the road will likely be considerably easier if you are clear as to whether you really have a new resource in each version, or a shared resource with different representations. If someone changes /v2/users, should that also change /v1/users? What are the correct cache invalidation semantics?

REST API design for non-CRUD actions, e.g. save, deploy, execute code

Resource in my REST API context is application code written in some programming language. CRUD operations that can be easily mapped to HTTP verbs are save/edit/delete code. Non-CRUD operations that are difficult to map to HTTP methods are deploy the code on server, execute the code, and undeploy.
Common suggestions I came across in SO are:
Restructure the action to appear like a field of a resource, e.g. if your action is to activate an engine, design URI: PATCH engines/123, body: {"status":"active"}
Treat the action like a sub-resource, e.g. PUT engines/123/active without a body
Use query parameters, e.g. PUT engines/123?activate=true
Be pragmatic and go for a non-RESTful, RPC-style URL, e.g. PUT engines/activate?id=123
I am definitely not able to fit deploy/undeploy/execute code actions to a resource as suggested in #1 and #2. Could you please share your opinion how best we can design the APIs for these actions?
Could you please share your opinion how best we can design the APIs for these actions?
Create/Update/Delete information resources, and as a side effect of that, do work behind the API.
So think documents.
One very good example: In RESTful Casuistry, Tim Bray asked about an api to shut down a machine. Seth Ladd's response, in particular, is important to read
Fundamentally, REST is a bureaucracy that solves problems with paperwork. If you want to get anything done, you submit the right form; which becomes an information resource describing what you want done.
PUT /deploymentRequests/abcde
Please find the artifacts from build 12345 and deploy that artifact
to machine 67890
201 Created
The request is just a document, in exactly the same way a sticky note on your desk asking you to address some task is a document.
As far as REST is concerned, the spelling of the URI absolutely does not matter; but from the point of view of a human readable naming convention, start from the fact that the resource is the document -- not the side effect that you want the document to have.
So, for example, it's totally normal and compliant with REST that the document that describes the current state of a thing and the document that describes changes you want to make to a thing are different documents with different identifiers.
I think you are looking for controllers, according to REST API design RuleBook:
A controller resource models a procedural concept.
Controller resources are like executable functions, with parameters and return values; inputs and outputs.
Like a traditional web application’s use of HTML forms, a REST API relies on controller resources to perform application-specific actions that cannot be logically mapped to one of the standard methods (create, retrieve, update, and delete, also known as CRUD).
Controller names typically appear as the last segment in a URI path, with no child resources to follow them in the hierarchy.
The example below shows a controller resource that allows a client to resend an alert to a user:
POST /alerts/245743/resend
and also:
POST should be used to create a new resource within a collection and execute controllers.
CRUD operations that can be easily mapped to HTTP verbs are
save/edit/delete code. Non-CRUD operations that are difficult to map
to HTTP methods are deploy the code on server, execute the code, and
undeploy.
I think you misunderstood the whole concept. You map operations to the HTTP method and URI, not just to the HTTP method. In the case of CRUD this is evident. In the case of "non-CRUD", you need to add a new resource with a different URI instead of trying to add a new HTTP method to the list.
PATCH is for updating a resource just like PUT, but in the case of PATCH you send update instructions instead of a representation. Sure it can be used or POST can be used too. Using PUT is not a good idea if you don't send a representation of the new resource state in the body.
So any of these can be good:
PATCH engines/123 "activate"
PUT engines/123/state "active"
POST engines/123/activation null
You can do the same with "deploy/undeploy/execute":
PATCH engines/123 "deploy"
PUT engines/123/state "before-deploy"
POST engines/123/execution null
This is just a recommendation though. You can choose the verb based on the HTTP standard and I think it is better to avoid using verbs in the URI, I use just nouns, because it makes sense this way. The URI is not that important though, it is like nice URIs on web pages, it looks good, but nobody really cares unless they have to write it down. Just to make it clear, this is still not REST unless you send these hyperlinks in your responses.
{
id: "engines/123",
type: "docs/engine",
operations: [
{
operation: "docs/engine/activation",
id: "engines/123",
method: "PATCH",
body: "activate"
}
]
}
Using RDF and ontologies takes this a lot further.

Complex domain URL structure with RESTful

I'm building a RESTful wrapper around quite complex underlaying domain. I built a domain model using UML packages and classes and derived REST-resources from the meaningful classes.
When it came to the endpint-URL design, I decided to map the package/class structure directly to URLs in order to streamline the process and have a neat traceability between my logical model (domain) and physicall implementation (REST API).
Let's say I have a following domain extract:
Admin and Work are packages, while User, Permission and Task are classes (REST Resources).
I derived the following endpoint URLs from this domain:
mydomain/admin/user -> Users collection
mydomain/admin/user/id -> User instance with id
mydomain/admin/user/id/permissions -> All permissions of the User with id
mydomain/work/task, and so on...
A collegue of mine noticed that the URLs are not optimal, mainly because these "package" parts do not map to the concrete resources. For example "admin" is not a Resource and is part of the URL. As the domain structure grows, there will be even more these intermediary non-resource-segments in the URL and he finds it wrong.
I find it nice, as URL structure itself tells something about the resource and is backed up with a complete, well documented domain model.
Is this a violation of RESTful standard?
Is this a violation of RESTful standard?
No. REST has no opinon on how an URL should look. You could use an URL like
/foo/bar/baz?qux=12
without violating any REST principle. Such an URL has no meaning for a human reader but that doesn't matter.
It is not necessary that every parts of an URL like
/foo
/foo/bar
maps to a resource. In fact is is a common misconception that RESTful URLS must follow some pattern or build rule. That is not the case.
Of courese there are best practices commonly used. One such practice would be to have collection resources like
/mydomain/admin/user
and single resources like
/mydomain/admin/user/42
But, again, that is not required by REST.
The REST architecture doesn't dictate what your URL's should look like. So, from that perspective, you're not violating any rules.
Instead, an important aspect of REST is that one should be able to use hyperlinks in order to navigate from one URL to another (something we are all used to when browsing HTML websites, but is not as common in REST APIs). Using links, consumers of your web application (wether they are humans using a web browser, or other applications that are using your API) can discover the available URLs, and the actual structure of your URLs doesn't really matter. Your URLs can even change without breaking other applications, because they will simply follow the link to the new URL.
So from a REST perspective, you could use whatever URL structure you like. As long as you provide a fixed entry point that provides a link to your users collection, the actual URL could be anything.
However, it is obviously still helpful when URLs are easy to understand and somewhat predictable. For instance, right now you have collections with a singular URL (yourdomain/admin/user) and collections with a plural URL (yourdomain/admin/user/3/permissions), which isn't very consistent. I'd suggest using only plural names, so yourdomain/admin/user becomes yourdomain/admin/users.
As for your actual question, as I mentioned this doesn't matter from a REST perspective. More important is that the URL makes clear what it represents. Something I'd take into consideration is the amount of different endpoints you're gonna have. If you are building a small application, with a small amount of endpoints, I'd keep it simple. But if you are creating a very large application with a lot of domain models, prepending them with some kind of categories sounds like a good idea.
Conclusion
URLs in a REST API should be discoverable by hyperlinks, and therefore no hard rules exist. Just make sure your URLs make sense to anybody who has to dig into them.
Some tips for usefull URLs can be found in REST-ful URI design.
You aren't following the strict definition of being RESTful; but it's not due to your colleague's concerns.
Your main challenge is that your proposal has the endpoints baked in to the client applications. A client looking for a user goes straight to /mydomain/admin/user.
But if (and when) you re-locate that endpoint, say /mydomain/admin/department/user, your clients are now broken.
The solution:
REST defines that you have one (or very few) endpoints, termed "Cool URIs", which are fixed enough that they never change.
Instead of your client going to the endpoint of /mydomain/admin/user they will take this approach:
Retrieve a root object from /mydomain (the Cool URI). => "mydomain" service object.
"mydomain" object contains a URI which has the identifier of "admin". Follow that URI.
"admin" object contains a URI which has the identifier of "user". Follow that URI.
"user" object returned (more likely a list of users).
In this respect, there is no reliance upon the client application having to know the URI format; therefore when you change the endpoints, you just change the URIs that your service embeds in the returned REST objects.
This approach to REST, where each returned object contains the URI to the next, is part of the HATEOAS principle.
If you're worried about how a client will pull back a given ID number (e.g. user 42), then that's catered for too: you can implement something like OData. So again, the URI is provided by the parent object. Instead of the client using a pre-baked endpoint like this:
/mydomain/admin/users/42
...it instead does this:
/mydomain (Cool URI)
Follow the link for "admin".
Follow the link for "users", appending ?$filter=UserId eq 42
There are also some really good concepts around solving object versioning issues, which again are difficult if you take the approach of hard-coding the endpoints upfront.
If it's any consolation, I started off defining my REST architecture around fixed endpoints (as you are), and then discovered that using a true RESTful approach is actually simpler in the long run.
Best of luck!

Non-contextual operations using REST and HATEOS

I am trying to implement HATEOS based REST service for hotel booking but have this confusion:
1) How does apart from WADL, the client comes to know about possible operations and their corresponding URI. Should I put all possible operations and URI as response when the client hits the root of REST service?
2) When the client gets a list of all accommodation options in an area, I am returning a list of all hotels in the area he asked about. The response contains:
<accommodation>
<hotel info="http://welco.me/hotel/xxxxxx" price="5000"/>
<hotel info="http://welco.me/hotel/yyyyyyy" price="3000"/>
</accommodation>
But the query I have here is how the client is going to know about other related possible operations like getting the list in sorted order of price?
In answer to your first question, there are a couple of specs for documents that allow clients to discover RESTful APIs.
Swagger
JSON Home
Google use their own Discovery Service, however unlike Swagger and JSON Home, unfortunately I don't think there are open sourced libraries that help you use expose it for your own APIs.
For Your second questions again, I would tend towards clients/developers discovering parameters such as sorting from the Swagger/JSON Home document. However if it is a super strong/important relationship you could also return it in the responses as linked data:
In HAL you can provide a links object with links to related resources.
In JSON-LD you can add a field with a value of the related API url. You may then add an #content to add information describes what that relationship means.
You should use link hints. An older way of doing this, the OPTIONS method, has some longstanding caveats.
Include links that use a custom link relation something like http://welco.me/#sort-by-price where you define the URI to mean whatever you want it to. You should provide some developer documentation at that URI but the client app will never dereference it, it merely uses the URI as an opaque string for equality comparisons.