I'm creating an API which would allow users to create, update and delete blog posts. I've got to the point where I want to now create an update handler for the blog post but creating a model for this call got me thinking..
For a PUT request should the id of the blog being updated be within the URI or be within the body like so:
In the URI:
/api/blog/23
In the body:
{
"id": "23",
"title": "new blog title"
}
Is there a right and wrong? If not, then what is generally the most followed convention for RESTful api's?
Technically there is no right or wrong way to design an API. However, a well designed API will be much easier to understand.
Assuming this is a REST API, my preference is to stay consistent. If your API requires an ID within the URI to GET resources then keeping things consistent with an ID in the URI to PUT would be my recommendation.
Microsoft has a good API design guidance article which also recommends to keep URIs consistent.
PUT, in HTTP, means something very specific
The PUT method requests that the state of the target resource be created or replaced with the state defined by the representation enclosed in the request message payload.
It's a request that asks the server to change the servers copy to match the representation provided by the client. Think "Save", or "Overwrite" -- a content management action.
So if the JSON representation of this blog post should be an id, a title, and nothing else -- then that would be fine.
If you intention is to change the title, while leaving the rest of the representation unchanged, then you either need to (a) send the entire representation, including your edit or (b) choose a method with different semantics (POST or PATCH could make sense).
The URI is an identifier -- think key in a hashtable/dictionary. There's no particular reason that data encoded into the identifier needs to match data in the representation. It certainly can -- we'll often encode into the URI information that the server will use in its own internal implementation -- but /4ca7fce6-efce-42d1-8fc6-666c3cae4f90 is a perfectly valid identifier for a resource.
Related
I'm writing RESTful APIs and am getting used to the recommended protocols for using HTTP verbs for different operations.
However, I'm not sure how those protocols handle the case where you are deleting a potentially long list of items.
It appears that, like GET, the DELETE verb has no body and so is limited to the length of a URL. So how could you support accepting an arbitrarily long list of items to be deleted?
From the top....
HTTP is our standard for self-descriptive messages, which is subject to the uniform interface constraint. That in turn means that everyone on the web understands HTTP requests the same way.
In other words
DELETE /api/users/5b45eda8-067c-42c1-ae1b-e0f82ad736d6
has the same meaning as
DELETE /www/home.html
In both cases, we're asking the server to enact a change to its resource model.
Because everyone understands these requests the same way, we can create general purpose components (ex: caches) that understand the meaning of messages in the transfer of documents over a network domain and can therefore do intelligent things (like invalidating previously cached responses).
And we can do this even though the general purpose components know nothing about the semantics of the resource, and nothing about the underlying domain model hidden behind the resource.
DELETE, in HTTP, always specifies a single target URI; "bulk delete" is not an option here.
(I haven't found any registered HTTP methods that describe a bulk delete to general purpose components. It's possible that one of the WebDAV methods could express those semantics, but the WebDAV standard also has a lot of other baggage - I wouldn't try repurposing those methods for a "normal" API.)
So if you are trying to DELETE three resources in your API, then you are going to need three requests to do it -- just like you would if you were trying to DELETE three pages on your web site.
That said, if deleting a bunch of resources on your web site using a single HTTP request is more important than letting general purpose components understand what is going on: you have the option of using POST
POST serves many useful purposes in HTTP, including the general purpose of “this action isn’t worth standardizing.” -- Fielding, 2009
General purpose components will understand that the resource identified by the target URI is changing in some way, but it won't understand what is happening in the payload.
In theory, you could standardize a payload that means "we're deleting all of these resources", and then general purpose components could be implemented to recognize that standard. In practice, good luck.
Now, if instead what you want is a bulk delete of entities in your domain model, you have some options available.
On the web, we would normally use something like a form - perhaps with a check box for each entity. You select the entities that you want to delete, submit the form, and the HTTP request handler parses the message, then forwards the information to your domain model.
You could achieve something similar with a remote authoring idiom - here's a resource whose representation is a list of entities. You PUT to the server a copy of that document with entities removed, and then on the server you make changes to the domain model to match.
It's a very declarative approach: "change the domain model so that the representation of the resource will look like this".
This is analogous to how you would use HTTP to fix a spelling error in a web page: send a PUT request with the new HTML (including the spelling correction) in the request body.
PATCH is very much the same idea: we describe changes to the representation of the resource, and the server passes that information to the domain model. The difference here being that instead of sending the entire representation, we just send a patch document that describes the correction.
If you want an imperative approach - just use POST
POST /Bob
Content-Type: text/plain
Bob,
Please delete domain entities 1, 2, 5, 7
General purpose components won't understand how you are trying to modify the target resource, but they'll at least know that much.
Where things get messy is when there are lots of resources whose representation depends on the same resources. The standards don't offer us much in the way of affordances to announce "here are all the resources that have changed".
Cache invalidation is one of the two hard problems. HTTP has some affordances that work in the simple cases, but trade offs become necessary when things get more complicated.
I have an issue with naming endpoints in a REST api.
Let's say you have a UI on the client side and in that UI is a table with a list of files. When tapping on a file it will proceed to download that selected one from the server. Additionally there is a button that when clicked will download all the files or selected files.
So the endpoints on the API may be structured like so...
[GET] Api/Files/{fileName}
Gets a single file by the file name provided in the route.
[GET] Api/Files
Gets a list of the files, including: FileName, Size, Type, etc...
[GET] Api/Files
Gets the files, returned as a ZIP file.
As you can see the issue is the conflict of endpoints with Api/Files. I would expect both endpoints to do what I have specified that they do. But one of them needs to change... I've thought about adding something to the end but mostly verbs come to mind. Any ideas on how the formatting could be done?
Going over the different answers and testing them out, I think the best answer is just having a different endpoint name. So I've now gone for...
[GET] Api/Files/{fileName}
Gets a single file by the file name provided in the route.
[GET] Api/Files
Gets a list of the files, including: FileName, Size, Type, etc...
[GET] Api/Files/Archive
Gets the files, returned as a ZIP file.
It's not perfect, but it makes sense.
An alternative could be...
[GET] Api/Files/Zip
But I think this doesn't work very well. As endpoints should never change and I may want to change it from a zip at some point...
The HTTP/RESTy way is to specify the response type you want with the Accept header. The endpoint can return the results as JSON if Accept is application/json and a ZIP file if it's application/zip
In the worst case, you can inspect a request's Accept header and return either a JSON result or create a ZIP file and return it with return File(...).
The Produces attribute can be used to specify the content type returned by each action, allowing you to write different actions for each content type.
Another option is to create a custom output formatter and have ASP.NET itself handle the generation of the ZIP file when the Accept header requests it. This blog post shows how to create an Excel Output formatter which returns a List of items as an Excel file when the Accept header requests this
I would expect both endpoints to do what I have specified that they do. But one of them needs to change...
Right - expanding on that idea, you have three resources (the contents of the file, the list of available files, the downloadable archive of files), but only two names; so you need at least one more name.
Good news: REST doesn't care what spelling conventions you use for your resource identifiers, so you don't actually need a good name.
/Api/0d660ac6-d067-42c1-b23b-daaaf946efc0
That will work just fine. The machines don't care.
Human beings do care though; it will be a lot easier to review an access log, or find things in documentation, if we aren't trying to guess what the different UUIDs mean.
mostly verbs come to mind
Verbs are fine. Notice that these URI all work exactly like you would expect:
https://www.merriam-webster.com/dictionary/get
https://www.merriam-webster.com/dictionary/put
https://www.merriam-webster.com/dictionary/post
The HTTP/RESTy way is to specify the response type you want with the Accept header.
Probably not what you want, here. The effective target uri is the primary cache key; when we invalidate a cached entry, all of the representations will be invalidated. If that's not the relationship you want between your list of files and your downloadable zip, then having them share a resource identifier is going to be unhappy.
Accept makes more sense when you have multiple representations of the same thing (ie, the list of files, but represented as HTML, JSON, text, XML, etc).
You might also consider what these identifiers look like in the access logs; should the list of files and the zip be logged using the same URI? Do you want general purpose log parsing tools (like alarm systems) to consider the two different kinds of fetch to be equivalent?
I have a .NET .ashx handler, which receives a jQuery AJAX post, formats a web service request to a third-party service and consumes the result. On success, it instantiates an anonymous object with the relevant information and formats a JSON response string.
In the event of a web service error, I do the following:
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
context.Response.StatusDescription = wsResult.ErrorCode;
This makes both the status code and description easily accessible to the jQuery AJAX error callback; however, the way I have implemented this is quite arbitrary.
After doing some reading around, I can't find a conclusive answer to the following question: Is there an accepted, universal convention (or - even - specification) for returning error states to JSON-based AJAX calls, which allows any consumer to know what to expect, or is this as arbitrary as a return type for any other function call?
So, is this a perfectly acceptable way of returning an error status to the AJAX caller, or is there a "proper" way of formatting a JSON error response?
As others have said, there's no universal convention. The REST "community" is still in the process of finding some consensus in matters like these - a consensus may never be found. Just to give a few examples:
Status code
By default ServiceStack.NET, a widely used C# REST library web service framework, returns the object (or empty response) with a status code, e.g.:
201 Created
Or:
200 OK
In the case of a validation error (e.g. an ArgumentException), it may do e.g.:
400 Bad Request
And here's already the first point where things start to vary. Some people like the 400 status code for things like validation errors - others don't, since 400 really indicates malformed syntax in the request format itself.
Some prefer 422 Unprocessable Entity for validation errors, a WebDAV extension to the HTTP protocol, but still perfectly acceptable technically.
Others think you should simply take one of the error status codes unused in the HTTP protocol, e.g. 461. Twitter have done that with (among others) 420 Enhance Your Calm to notify a client that they're now being rate limited - even if there's an (on the surface) acceptable (and recommended) status code 429 Too Many Requests for that purpose already.
Etc. It's all a matter of philosophy.
As for 500 Internal Server Error, the same applies - some think it's perfectly fine for all kinds of error responses, others think that the 5xx errors should only be returned on exceptions (in the real sense - i.e., exceptional errors). If the error is truly exceptional, you mostly wouldn't want to take the chance and pass on any actual exception info, which may reveal too much about your server.
Leading us to what (if anything) to return in the JSON result? Same thing...
Response
200 OK may be quite enough for responding to e.g. a request to delete a resource, if no error occurred. In the same way, 404 Not Found is enough to tell the client that the requested deletion couldn't be performed because the entity to delete wasn't found. In other cases you may require more than that.
Some people think you should include as much of the needed info as possible in the response headers, often having an empty response with only headers. For example, on a creation, return 201 Created and put the created entity's ID (as a resource URI) in Content-Location. No response content needed.
I personally think that if you're making a public API, it's a good idea to return both appropriate headers and content, even if the content is somewhat redundant. I.e.:
HTTP/1.1 404 Not found
Content-Type: application/json; charset=utf-8
...
{
'Success': false,
'Message': 'The user Mr. Gone wasn't found.'
}
(I don't actually include the Success property, but I might want to, depending on my frame of mind when designing the API).
When running in DEBUG mode, I also include a string representation of the internal service call - e.g. 'Request': 'GetUser { id: 5 }', a timestamp, and the stack trace. It's all a matter of convenience, though. It's easy enough to code a client with proper user friendly error messages simply based on 404 Not found. Some other errors (e.g. validation) may need more context, though. For example:
HTTP/1.1 422 Validation Error
Content-Type: application/json; charset=utf-8
...
{
'Success': false,
'Message': 'The request had validation errors.',
'Errors':
{
'UserName': 'The user name must be provided.',
'Email': 'The email address is already in use.'
}
}
ServiceStack.NET does something like this by default, but with slightly different properties and content. Microsoft's own Web API framework does something similar.
The JSend spec linked in the related question is another variation.
And so on.
In short, no, there isn't any universal convention - not yet, at least. Lots of people (putting more thought into it than I) are working on it. But still, there may never be. And your method is perfectly acceptable.
(Yes, this was very lengthy - mostly because I've been searching around for the same kind of "universal convention" for a while).
For more on status codes, this is an excellent article (too long to quote here)
No, there is not any single major standard out there, although this might be nice. It might be useful if you are making yourself a standard to include success and details, but it depends on exactly how you are using it. I think the big advantage is when you implement a standard at least across all of your own code for consistency, e.g. http://ricardocovo.com/2012/03/08/asp-net-mvc-using-json-standard-responses-for-your-ajax-calls/
Your response is completely acceptable if it's fitting your needs. If I was working with an API, I would see that error response as 'standard', containing a response code and description, although I might like a boolean success for ease of use.
My 2 cents:
I would say that foremost the statuscode that you send back as the response is the best error indicator and gives a lot of options in the 4xx and 5xx range... (Even when you try to HttpGET some coffee from a teapot, you can use 418 :D)
As anything that is not 200 is some sort of error, and the http status codes are well documented in which case they should be used, any further error message is not really necessary (The error description is implied by the statuscode). Browsers are the ones doing the request, and they don't care about the errormessage, only the statuscode.
Any extra errormessages might also just away too much information to possible hack attempts. I mean, returning a 403 Forbidden is enough information on its own, you shouldn't also return a message saying "Not allowed, please use '1234' as the password instead" :)
Google JSON Style Guide uses data xor error objects ...
In order to maintain a consistent interface across APIs, JSON objects should follow the structure outlined below. This structure applies to both requests and responses made with JSON.
. . .
The JSON object has a few top-level properties, followed by either a
data object or an error object, but not both.
An example ...
{
"apiVersion": "2.0",
"error": {
"code": 404,
"message": "File Not Found",
"errors": [{
"domain": "Calendar",
"reason": "ResourceNotFoundException",
"message": "File Not Found
}]
}
}
I generally adopt the names, structure and content of the server-side system as a matter of practice.
This practice ensures that front-end developers communicate to back-end developers using a vocabulary they already understand, and it doesn't set a standard/precedent whereby back-end developers are tasked with implementing new formats as front-end developers and designers invent new concepts (an error is an error, let's not split hairs about "type" and "meta", which are mere attributes of any given error.)
So, for example, if I'm returning error details to "a JSON client" and the service endpoint is implemented using C#, I would want to return a JSON document which looked like this:
{
"Message": "An error has occurred.",
"ExceptionMessage": "Index was outside the bounds of the array.",
"ExceptionType": "System.IndexOutOfRangeException",
"StackTrace": " at WebApiTest.TestController.Post(Uri uri) in c:\\Temp\\WebApiTest\\WebApiTest\\TestController.cs:line 18\r\n at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClassf.<GetExecutor>b__9(Object instance, Object[] methodParameters)\r\n at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.Execute(Object instance, Object[] arguments)\r\n at System.Threading.Tasks.TaskHelpers.RunSynchronously[TResult](Func`1 func, CancellationToken cancellationToken)",
}
Not to parrot the accepted answer, of course, I only want to convey that the value in uniformity is enormous, especially if you're a polyglot (or "an entirely new programmer" who is simply not sure of one way or another.)
It may not matter to you now, but in 2, 3, or 5 years of maintenance you may start caring, and you may find yourself having to "retrain" in the long run as you run into other developers that embrace a similar practice of conformity and you're the only guy on the team still trying to invent new formats (when it's not necessary.)
NOTE: To be clear I am not suggesting you serialize exceptions down to the client. Although, that may be a perfectly valid option in many scenarios including debugging, secure private clouds, or when there is no sensitive data/IP, etc.
I'm looking at developing an application in ASP.NET MVC 3 and would like to provide a public API at the same time.
From looking around, there seems to be 2 ways to go about it. Either create an API area and have controllers that return json / xml. Or use action filters and a single front end set of controllers, and have those return json / xml / html depending on the request headers.
I'd like to do the later, but I was wondering how you could go about versioning your api if you went this route?
If you go the first route, you could easily just create a v1 / v2 controller, but if you do the later, how could you version it?
Versioning is a rather complex issue to begin with. Here are ways I looked at before:
URL. In this case https://api.example.com/v1/projects is assumed to be a different resource than http://api.example.com/v2/projects, even though its not the case. Basecamp seems to do this. Following this approach, assume you'll always have to support old APIs.
Headers. The URLs remains the same, however, the client pass an additional HTTP header, say X-MYAPI-VERSION with each request with a value identifying the version of the API to use. The Google Documents List API do this. A potential problem with this approach is that HTTP headers may be stripped by intermediaries between the client and server.
Parameters. To circumvent the problem with option 2, you can pass the API version to use as a parameter (such as https://api.example.com/projects?v=3).
Media types. Here your URLs stay the same, however, users are required to specify the representation of the resources using the accept and content type headers. For example, a "project" can be presented using "application/vnd.mycompany.resource[-version][+format]" giving your representations of "application/vnd.mycompany.project-v1+json" for v1 json or "application/vnd.mycompany.project-v1+xml" for v1 xml. When you need a new version of a project comes along the mime type may look as follows "application/vnd.mycompany.project-v2+xml". Github seems to support that.
Part of payload. In this case the payload of the request contains the version number to use. For example, when XML is passed, you can look at the namespace to determine which version of the API is being used. For JSON, you can use a "$version" or "_version" property to specify the version.
Client Key. When the application is registered, it specifies which version of the API it wants to use. When you authenticate the client, you ensure that you emulate the version it wants to use.
No explicit versioning There is always the option not to version your API and try to handle changes transparently by making all fields optional and handle them appropriately when they are missing. Chances are you will be doing this anyways to make future versions of your API compatible with the version you are developing today.
Many recommend option 4, although its not always practical. Most of these options require additional work to get working with ASP.NET MVC.
You can go one of two routes - you can include the API in the route (instead of http://app.lication/category/1 you would have something like http://app.lication/api/v1/category/1) or you could include a custom HTTP header.
Either will allow you to discriminate which version's being called.
I'm not sure if I'm asking the right question.
We have a web app that we're trying to have a 3rd party POST to. We're creating a special landing page for them to which they can submit the data we need via POST.
I'm not sure how to respond to their request, which I assume I handle as an incoming HttpRequest. Do I process their data in PageLoad or some other event? Where/How is this data contained?
Do I have to use HttpListener or the ProcessRequest handler, or what?
Doing a search here or on Google turns up a lot of results on how to POST to another site, but can't seem to find a relevant site on how to be that "other" site and handle the incoming POST data.
Again, I'm not sure I'm asking this right.
EDIT: I found the Page.ProcessRequest Method in the MSDN library, but the Remarks say "You should not call this method"
Thanks!
You really need to look at the basics of ASP.NET. Even if this were a case where an IHttpHandler would be best-suited, I'd suggest using an .aspx page in this case as it's the best place to begin learning, and you can move to an IHttpHandler later on.
If the data is posted in application/x-www-form-urlencoded or multipart/form-data (the two formats used by forms on web pages - if they haven't told you what format they are using then it's probably one of those two), the Request.Form property (actually, a property of a property) will act as a dictionary into the data sent (e.g. if they have a field called "foo" then Request.Form["foo"] wll return the value of it as a string). Otherwise you'll want to use the Request.InputStream and read from that. This latter is a tiny bit more involved though.
Best would be to use an IHttpHandler, but it is possible to do what you want using a standard ASP.NET Page. Using PageLoad is fine, you have access to the Request and Response properties, which give you everything you need to process an HTTP request. For example, to obtain form parameters, you can use Request["input1"] to get the form input value (either query string, form post, or cookie) with the name "input1".
What is it you need to do in response to this post request? What sort of data do you need to return? Until that is answered, hard to help further.