I have a set of actions that are returning time-series data with-in ranges specifiable to the minute.
They work fine with querystrings,
i.e.
/mycontroller/myaction?from=20091201 10:31&to=20091202 10:34
with or without URL encoded colons, but I thought it would be nice to have a pretty URL
/mycontroller/myaction/from-20091201 10:31/to-20091202 10:34
but this now strikes fear in the hear of IIS as it doesn't like colons in the URI so I get 'Bad Request' responses.
My question then, is what's a recommended/standard course of action to ensure I can keep the time in there?
Do I need to write a custom ModelBinder to parse my own datetime format? Should the actions just take strings for from and to and parse with a custom format eg "YYYYMMDD-HHmm". Can I specify a custom format somewhere? If so where? Or should I just give this up as folly and stick with querystring parameters?
Oh, and I see a lot of people go on about RESTful URLs; from what I've read there's nothing that says query strings aren't RESTful - it's more about appropriate use of existing HTTP action types.
You're right REST doesn't mean if it's its not in a folder structure its not REST.
The path structure is there to describe the resource. Querystrings can still be used to describe a filtered subset of such a resource. A date range fully qualifies as a filter criteria and should thus be perfectly RESTful being passed in as a querystring.
Related
How do I clear/remove query string parameters, which my MVC action, doesn't require/support?
For instance, my action requires, say an id and a bool flag, so the url would be something like: http://localhost:someport/controller/action/?id=1&remove=true
But, if a user types in something like, http://localhost:someport/controller/action/?id=1&remove=true&some-junk-param=0
Then, I want the some-junk-param to be removed and not shown in the address bar, when the request is processed.
Any thoughts?
If you need to get rid of unwanted query string parameters, you have two general options:
Do it on server-side. You can achive this only with redirection, that means when browser asks URL with bad query string, server redirects browser to URL with good query string.
Caveats:
In this case we have redundant query just for cleaning query string.
User will have trash in browser history.
Do it on client-side. ASP.NET MVC Model binder will get only expected parameters from query string, so it's nothing bad with having other values in query string. You can check your URL on client-side with javascript and rewrite it with or without changing history using History API (IE10+).
Caveats:
In this case you will have to support consistency about allowed parameters between JS and C# code
Of course every way is suitable for it's own cases, but looking at caveats the second way is better, because it affects developer expirience whereas first way affects user expirience.
I'm reading the book, HTTP - The Definitive Guide, from which I get the URL general format:
<scheme>://<user>:<password>#<host>:<port>/<path>;<params>?<query>#<frag>
The <params> part said,
The path component for HTTP URLs can be broken into path segments. Each segment can have its own params. For example:
http://www.joes-hardware.com/hammers;sale=false/index.html;graphics=true
In my opinion, path params can also be used to query resources like query strings, but why it's barely seen?
And I'm a Rails developer, and I haven't seen its usage or specification in Rails. Does Rails not support it?
You ask several questions
Why do we not see ;params=value much?
Because query parameters using ?=& are widely supported, like in PHP, .net, ruby etc.. with convenient functions like $_GET[].
While params delimited by ; or , do not have these convenient helper functions. You do encounter them at Rest api's, where they are used in the htaccess or the controller to get relevant parameters.
Does Ruby support params delimited with ;?
Once you obtain the current url, you can get all parameters with a simple regex call. This is also why they are used in htaccess files, because they are easily regexed (is that a word?).
Both parameter passing structures are valid and can be used, the only clear reason why one is used more often than the other is because of preference and support in the different languages.
I have some easy to read URLs for finding data that belongs to a collection of record IDs that are using a comma as a delimiter.
Example:
http://www.example.com/find:1%2C2%2C3%2C4%2C5
I want to know if I change the delimiter from a comma to a period. Since periods are not a special character in a URL. That means it won't have to be encoded.
Example:
http://www.example.com/find:1.2.3.4.5
Are there any browsers (Firefox, Chrome, IE, etc) that will have a problem with that URL?
There are some related questions here on SO, but none that specific say it's a good or bad practice.
To me, that looks like a resource with an odd query string format.
If I understand correctly this would be equal to something like:
http://www.example.com/find?id=1&id=2&id=3&id=4&id=5
Since your filter is acting like a multi-select (IDs instead of search fields), that would be my guess at a standard equivalent.
Browsers should not have any issues with it, as long as the application's route mechanism handles it properly. And as long as you are not building that query-like thing with an HTML form (in which case you would need JS or some rewrites, ew!).
May I ask why not use a more standard URL and querystring? Perhaps something that includes element class (/reports/search?name=...), just to know what is being queried by find. Just curious, I knows sometimes standards don't apply.
I have developed a ASP.NET MVC application. I have a conroller with the name EmployeeController and it got a method called GetEmployeeByName. GetEmployeeByName() takes a name of type string as parameter.
So When I send a request like this, i get the data back :
someDomain:9999/Employee/GetEmployeeByName/Roger Federer
But if the name contains an '&' (you & me), I get a '400 Bad Request' as response from server.
someDomain:9999/Employee/GetEmployeeByName/you%20&%20me
Even if i encode it dont get a reposne back
someDomain:9999/Employee/GetEmployeeByName/you%20&%20me
What is the right way to encode such (data with special character) data?
What is the right way to encode such (data with special character) data?
The right way is to use a query string parameter and not be putting those things as part of the uri portion. Read the following blog post from Scott Hansleman. I will only quote hos conclusion:
After ALL this effort to get crazy stuff in the Request Path, it's
worth mentioning that simply keeping the values as a part of the Query
String (remember WAY back at the beginning of this post?) is easier,
cleaner, more flexible, and more secure.
As you can see in the blog post there are some hacky ways to make it work and circumvent IIS handling but it simply is not something that I would recommend you venturing into. Just put this name in the query string.
Suppose you are working on an API, and you want nice URLs. For example, you want to provide the ability to query articles based on author, perhaps with sorting.
Standard:
GET http://example.com/articles.php?author=5&sort=desc
I imagine a RESTful way of doing this might be:
GET http://example.com/articles/all/author/5/sort/desc
Am I correct? Or have I got this REST thing all wrong?
I'm afraid your question really misses the point of REST. From a purely theoretical perspective there is absolutely no advantage or disadvantage to either of those urls from a REST perspective. In practice, those urls may behave differently with different caches, and certainly server frameworks are going to parse them differently. Despite what you hear from the framework developers, there is no such thing as a RESTful URL.
From the perspective of REST those two URLs are simply identifiers that can be dereferenced. If you want to start building REST apis that will benefit from the characteristics described in the dissertation, you need to start thinking in terms of content that is returned when you dereference the URL and how that content is linked together using URLs embedded in the content.
I realize this does not help you much in trying to resolve what you consider to be your problem. What I can tell you is that one of the major intents of REST is to allow your URLs to be completely under the control of the server and can change without impacting your client applications. Therefore, my recommendation is to pick whatever url structure works most easily with the framework you are using to serve the resource representations. Certainly do not look to the REST dissertation to tell you what is the right and wrong way of formatting your URLs and anyone who tells you that your URLs are not RESTful is confused. Probably what they are telling you is the server framework, they are used to using for creating RESTful interfaces, requires URLs to be structured this way.
It's not what your URI looks like that matters, it is what you do with it that matters.
Using a query string is not more or less RESTful than using path components. The URI Generic Syntax (RFC 3986, January 2005) defines that they're just as important in identifying the resource. So yes, as others point out, it's not important to REST. (Note that in the obsoleted-by-RFC-3986 RFC 2396, the query string was not defined to be identifying the resource, but rather a string of information to be interpreted by the resource.)
However, URI design is important, because as an owner of a URI namespace (i.e. the holder of the domain name where the URIs will live) you want the URIs to be long lived. As wise men have stated earlier: Cool URIs don't change!
The choice of using query strings vs path components depends on how your resources are identified, and how they will be identified in years to come. If there's a hierarchy that stands out, then it might be that this should be reflected in the URI, at least if that hierarchy is relatively permanent, and that things don't move around all the time.
It's also important to note that the actual URIs are only meaningful to two parties:
Servers, who need to forge and parse URIs
Human beings who might see a URI in passing might learn things from the URI.
By contrast, client applications are usually not allowed to do URI introspection. So your choice of query strings vs path components boils down to what you think you can live with ten (or 100) years from now.
You are mostly right. The thing with REST api's is to focus on the nouns.
What does the noun all do in this case? Wouldn't you expect your API to always return all articles, unless you filter it?
I would make sort a query string parameters, further, I would make any and all filtering query string parameters. If you look at how Stack is implemented when you click on the "Newest" questions link, you get a query string to filter the questions.
So perhaps something like:
GET http://example.com/aritcles/authors/5?sort=desc
But also think about what happens with each URL:
GET http://example.com/aritcles/ might return all current articles
GET http://example.com/aritcles/authors/ What does this url do? does it return all authors of all articles, or does it return all the articles for all authors (which is essentially the same functionality of the URL above.)
GET http://example.com/aritcles/authors/5/ might return all articles by author 5, or does it return author 5's information?
I would maybe change it to:
http://example.com/aritcles returns all articles
http://example.com/aritcles/5 returns all articles from author 5
http://example.com/authors returns all authors
http://example.com/authors/5 returns information for author 5
Alan is mostly right but his URLs are misleading. I believe the correct routes / urls should reflect the following behavior:
[GET] http://domain.com/articles #=> returns all articles (index action)
[GET] http://domain.com/articles/5 #=> returns article ID 5 (show action)
[GET] http://domain.com/authors/#=> returns all authors (index action)
[GET] http://domain.com/authors/5 #=> returns author ID 5 (show action)
[GET] http://domain.com/authors/5/articles OR http://domain.com/articles/authors/5 #=> depending on the hierarchy of your routes (both belong to the index action)
Best regards,
DBA