15

I've seen this advice...

ideally the web should follow the REST principle and be completely stateless. Therefore a single URL should identify a single resource, without having to keep the navigation history of each user.

...and I read the Wikipedia page http://en.wikipedia.org/wiki/REST and it really sounds good, but I don't get how to actually implement it. I'm working in ASP .NET Webforms NOT MVC.

For example, in the application I am about to build - I need my user to Login before I allow them to do anything. There are a couple of hoops they have to jump through before they are allowed to do much useful - like Accept T's and C's and confirm their basic details are unchanged. Finally they are allowed to do something they really want like BuyAProduct!

It seems to me (I come from the HEAVILY stateful world of the Rich client) that I need state to record what they have done and infer from that what they are allowed to do. I don't see how I can support them (say) bookmarking the BuyAProduct URI. When they arrive at the bookmark how do I know if they have logged in and if they agreed to the T's and C's and if they dutifully checked their basic details?

I love the idea of the app being stateless, partly because it seems to completely solve the problem of "What the heck do I do when the user clicks on the Back and Forward buttons?" I don't see how I can still get it to work properly. I feel I am missing something really fundamental about this.

Cœur
  • 37,241
  • 25
  • 195
  • 267
RichardHowells
  • 7,826
  • 3
  • 24
  • 24
  • 1
    Why? If it is currently working, why change? Web applications tend to need to be stateful, hence Sessions and Cookies. – John Gietzen Jun 10 '10 at 16:34
  • Ah - it's not working as it's not built yet. I am thinking about design options. I will edit the question. – RichardHowells Jun 10 '10 at 16:35
  • 3
    @John I can assure that Web applications do not need to use sessions and cookies. – Darrel Miller Jun 10 '10 at 23:39
  • @Darrel Miller: What if you want to allow users to log-in to the app? – John Gietzen Jun 11 '10 at 00:46
  • 2
    @John The http Authorization header allows you to provide credentials with a request that can ensure the person doing the request is who they say they are and has sufficient authorization to make the request. What does being "logged on" do that cannot be achieved with the Authorization header? – Darrel Miller Jun 11 '10 at 01:06
  • @Darrel: Can you use OpenID with the Authorization header? – John Gietzen Jun 11 '10 at 12:11
  • possible duplicate of [If REST applications are supposed to be stateless, how do you manage sessions?](http://stackoverflow.com/questions/3105296/if-rest-applications-are-supposed-to-be-stateless-how-do-you-manage-sessions) –  Nov 21 '14 at 03:36

5 Answers5

24

The advice isn't suggesting that the app should be stateless - it's suggesting that the resources in the app should be stateless. That is, a page called "www.mysite.com/resources/123" will always represent the same resource, regardless of which user is accessing it or whether they're logged in or not.

(The fact that you might deny a non-logged-in user access is a separate issue - the point is that the Uri itself doesn't rely on user-specific data to work.)

For example, the kind of sites that break this rule are those where you navigate to a product page, email the Uri to your friend, and on clicking it they see a message along the lines of "I'm sorry, your session has expired" or "This product does not exist" or similar. The reason this happens is because the Uri includes something specific to the user's session on the site, and if a different user tries to use the link (or the same user at a later time), it's no longer valid.

So, you will always still need some form of state for your application, but where that state is implemented is the important factor.

Hope that helps shed a little light!

Dan Puzey
  • 33,626
  • 4
  • 73
  • 96
  • It would be helpful to note that in some cases, resources are user-specific, so only authorized users would see certain resources and not others. Thus, user-specific interactions are available. –  Jun 11 '10 at 06:58
  • Yes - but the Uri to that resource should remain the same for all users, whether they have access or not. (If this were a REST application, for example, you'd have the Uri return a Http Not Authorised state where relevant, instead of the resource). – Dan Puzey Jun 13 '10 at 13:35
  • So the state must be maintain in the client? Say, I have a link of A person www.XXXX.com/persom/Tom, and this website will deny stranger to get access, if I am his friend, I copy this link, and I will see his post, while if I am a stranger, it will be forbidden.Can I consider this relation ship as a state, since indeed the same URI gives us the different page. It must have something needs to maintain in the server, say in database to maintain the relationship.If this is a kind of state, and does this application stateless? – JaskeyLam Nov 21 '14 at 03:13
  • Your same URL should not give a different page, though. Technically, what should happen is that the URL when unauthorized should give a `HTTP 401` response, and the error page for that URL *could* be customised to show something useful (like a login form). Although the end result may appear as the user seeing a different page, your URL will only ever serve a single resource as the result of a *successful* request. It's a subtle difference, but it's the essence of the stateless model. – Dan Puzey Nov 21 '14 at 10:29
12

If you want to do Web forms, that's cool. If you want to do REST that's cool too. But please for the love of everything sacred, please don't attempt to adhere to the principles of REST using Web Forms.

Just to clarify this point further, I don't believe webforms is a wise choice for REST because the conceptual model that WebForms is based on is one where you abstract away the web. It was built to emulate the VB development model.

REST embraces HTTP and the distributed nature of web applications. The two approaches are not compatible.

Darrel Miller
  • 139,164
  • 32
  • 194
  • 243
  • No, I think you're wrong, in that the basic principle he's talking about can equally (and *should) be applied to WebForms too: don't put state information in your Uri. – Dan Puzey Jun 11 '10 at 09:02
  • @Dan I think what you meant to say is don't put a reference to server session state in the url. Putting client application state in the URL is a completely restful approach. Regardless, whether the session state is in the URL or is communicated in some other way, like a cookie, session state leads to violation of the REST self-descriptive constraint. – Darrel Miller Jun 11 '10 at 12:48
  • 1
    Application state in a Uri is completely contrary to the principles of REST: if *your* Uri to a resource is different to *my* Uri to a resource, that's not a RESTful Uri. – Dan Puzey Jun 13 '10 at 13:34
  • @Dan Once you add a query parameter to an URL you are referring to a different resource. It is not just the path segments that identify the resource. – Darrel Miller Jun 13 '10 at 13:48
  • @Dan In the example http://www.google.com/search?q=rest the search term can be considered application state. – Darrel Miller Jun 13 '10 at 13:51
  • @Dan Here is an even more interesting example: `http://yuml.me/diagram/scruffy/class/[Resource]+1-%3E*[Represenations]` – Darrel Miller Jun 13 '10 at 13:53
  • It could be considered state, but it's not. It doesn't change over time: it's a parameter, an input. It's not state that the application would change over time on behalf of the user. – Dan Puzey Jun 14 '10 at 07:45
  • @Dan I would be very interested if you could point me to some authoritative source that validates your perspective on client application state. – Darrel Miller Jun 14 '10 at 11:22
  • 1
    @Darrel I think what Dan is alluding to is this the Richardson Maturity Model: http://code.google.com/p/implementing-rest/wiki/RMM. Yes, you can do that, and yes, you can call it RESTful. But how RESTful is it, really? –  Jun 14 '10 at 22:51
  • @Ryan It is absolutely RESTful. It conforms the the uniform interface, the message is self-descriptive, it is one of the most straightforward examples of HATEOAS and it is an interesting example of using a virtual URI space for resource identification. Here is another example http://www.codestyle.org/servlets/FontStack?stack=Palatino+Linotype,Palatino&generic=serif – Darrel Miller Jun 15 '10 at 01:51
3

It is okay to maintain resource state. The "stateless prohibition" just refers to session state.

Here's an excerpt from Roy Fielding's seminal REST derivation:

We next add a constraint to the client-server interaction: communication must be stateless in nature, as in the client-stateless-server (CSS) style of Section 3.4.3 (Figure 5-3), such that each request from client to server must contain all of the information necessary to understand the request, and cannot take advantage of any stored context on the server. Session state is therefore kept entirely on the client.

Raymond Hettinger
  • 216,523
  • 63
  • 388
  • 485
  • How is this possible when the client (web browser) cannot store any secure information (aka credentials)? – BeniRose Jul 11 '16 at 16:04
1

Here's the thing: REST is about stateful communications over a stateless protocol. It's not that REST is stateless. WebForms enables you to retain state between requests. Why is that necessary? It let's you do things like sort items on a list with up/down buttons without having to update the underlying resource with each click. You don't need that. You could just PUT the resource representation so that it looks correct or use JavaScript to edit your representation and then do a PUT at the end once you are satisfied. (Note that I used PUT, not POST. What you are really doing is replacing the representation so that future GETs retrieve the right state.)

WebForms uses POST for everything. You should only POST to a URL when you are creating a new item and don't know where it will live. If you know its url, then you should use PUT to create or replace. If you need intermediary steps for, say, a shopping cart, then you should create resource representations for those intermediary steps. Your browser and server communicate by passing full representations between each other. It's simple request/response message passing.

WebForms doesn't encourage this. You can build RESTful systems in WebForms, but the default model will push you away from it towards a RPC approach. I can think of two ways around this: Front Controller (in which case you should really consider MVC) or using .ashx files for almost everything. The Postback model pretty well obliterates any real hope of doing true REST with real WebForms/.aspx (i.e. PUT and DELETE are always POSTs and thus fail the REST model).

  • As per RFC2616 POST can be used to send an entity to a processing resource. This does not imply creating of a resource. Creating is only one of the uses of POST. There is no requirement to use PUT and DELETE to be RESTful. See this FAQ https://code.google.com/p/implementing-rest/wiki/FAQ – Darrel Miller Jun 11 '10 at 12:59
  • @Darrel Fair enough. I probably lean too far towards being explicit. The problem I see is that it makes it too easy to explain everything away, which leads back to RPC. –  Jun 14 '10 at 22:49
  • @Darrel What I'm focused on is Level 3 of the Richardson Maturity Model: http://code.google.com/p/implementing-rest/wiki/RMM. Well, maybe level 2. :) –  Jun 14 '10 at 22:52
  • Yes, using POST for lots of things can easily lead back to RPC if people don't have clear understanding of the other REST constraints. – Darrel Miller Jun 14 '10 at 23:01
1

A cookie would seem to be the answer to your question. You can use the the .net authentication provider which will set a cookie, that your application can check for and require the presence for if they're to buy anything.

The thing you want to try and avoid is keeping a state representation of them on the server, aka session cookie. That will make scaling more difficult.

danswain
  • 4,171
  • 5
  • 37
  • 43